高雄市| 垦利| 镇康| 鄂州| 汤原| 中牟| 张北| 贺州| 龙口| 白碱滩| 新竹县| 永修| 汤原| 安龙| 庄河| 克什克腾旗| 亚东| 柘荣| 榆树| 宁蒗| 四平| 建阳| 阿瓦提| 木垒| 四平| 当雄| 西盟| 崇阳| 丹巴| 平远| 宁晋| 三门| 江永| 城步| 潼关| 李沧| 托克逊| 沈阳| 通州| 德钦| 古蔺| 泸溪| 金沙| 丹阳| 兴山| 牟定| 贵南| 同心| 吉木萨尔| 临夏县| 济宁| 辽宁| 仁布| 铁山港| 金湖| 阜康| 泽普| 台儿庄| 东辽| 洛南| 织金| 黄冈| 栖霞| 瓮安| 漾濞| 周村| 绥芬河| 峨山| 顺平| 阆中| 岳阳县| 资溪| 唐海| 科尔沁左翼后旗| 工布江达| 元氏| 邹平| 迁安| 宿豫| 普格| 浏阳| 大方| 阳高| 朗县| 新源| 丰润| 蒲城| 安溪| 德惠| 蛟河| 梁子湖| 云南| 西盟| 双柏| 克东| 黑山| 故城| 沿河| 洪江| 桃江| 合肥| 留坝| 嫩江| 新密| 武陵源| 湖州| 垣曲| 麻阳| 遵化| 章丘| 雷州| 深州| 湛江| 淳化| 贡嘎| 革吉| 白玉| 汶上| 礼县| 巴马| 泸州| 忻州| 奉化| 灵璧| 平遥| 肃南| 唐县| 瑞丽| 绵阳| 江宁| 阿克苏| 福山| 始兴| 凤阳| 莘县| 达尔罕茂明安联合旗| 寿阳| 万荣| 什邡| 汝南| 临湘| 浮山| 永顺| 彭州| 费县| 上高| 亳州| 金川| 普安| 威信| 伊宁县| 麟游| 临安| 兰州| 惠农| 福鼎| 玉屏| 宁武| 宾阳| 卢龙| 宜丰| 贡山| 林芝镇| 钟山| 赵县| 渝北| 温泉| 路桥| 衡南| 鹰潭| 栾川| 偃师| 互助| 普安| 大同区| 四川| 新河| 新蔡| 团风| 思南| 潞城| 东海| 望谟| 井研| 彝良| 靖远| 天柱| 沅陵| 大余| 固原| 汉沽| 古田| 保德| 西乌珠穆沁旗| 綦江| 府谷| 思南| 汾西| 南宁| 西沙岛| 黄冈| 荆州| 建瓯| 洞口| 新都| 陇西| 卓尼| 松桃| 定西| 景德镇| 德钦| 惠来| 陵川| 梅里斯| 越西| 图们| 任县| 横山| 黟县| 绛县| 兖州| 丰润| 莱芜| 顺平| 河口| 梅县| 图们| 十堰| 商河| 沙湾| 从江| 上思| 南票| 夷陵| 怀集| 潘集| 吐鲁番| 陈仓| 康县| 晋江| 彭州| 娄底| 奉新| 岳阳县| 赤城| 上饶县| 进贤| 容城| 西峰| 拜城| 阿拉善右旗| 永靖| 蒲江| 户县| 枣强| 南和| 淮南| 松潘| 安阳| 丰镇| 广平| 叶城| 嘉义县| 龙门| 百度

hp1008打印机驱动(惠普1008驱动下载) 官方版

2018-05-27 23:38 来源:中青网

  hp1008打印机驱动(惠普1008驱动下载) 官方版

  百度  事发于1月4日约凌晨3点,黎先生家被窃贼破门而入,屋内12张红木家具被连夜运走。(中新经纬APP)

展望今后一段时期,农业农村经济在保持平稳运行的同时,仍需关注三方面。故宫博物院藏石鼓、陕西历史博物馆藏懿德太子墓壁画《阙楼仪仗图》、辽宁省博物馆藏唐摹王羲之一门书翰卷、湖北省博物馆藏云梦睡虎地秦简、湖南省博物馆藏皿方罍、河南博物院藏云纹铜禁、浙江省博物馆藏玉琮、上海博物馆藏大克鼎、南京博物院藏大报恩寺琉璃塔拱门,一一呈现。

  在硬件设施和软件系统方面均按照国际顶级标准打造,在追求极致游乐体验的同时做到安全、卫生、人性化。  “团队将与四川省文物考古研究院一起努力,把先进技术应用在水下考古工作中,并不断总结经验,开创‘电子信息+考古’的新局面。

    第一届大会结束不久,我曾经做过一个总结,但是并不深入。但有时仍会感到,自己的皮肤状态并没有预想中那么好,这是为什么呢其实,一天当中最佳的护肤时间是在睡前,不仅要给肌肤做足够的护理,还要养成几个有益身心的好习惯,这样,皮肤自然会越来越好。

文/本报记者张钦(责编:沈光倩、杨虞波罗)

    他们在锂正极上涂了一层碳酸锂薄层,该层会让来自正极的锂离子进入电解质,同时防止其他化合物到达正极。

    原本空旷的箭亭广场上,如今布置了9座“小阁”,9个阁都是独立的LED高清展柜,9件国宝就“藏”在柜壁上。  当晚,郁可唯以一身清凉裙装亮相,纤细的大长腿格外抢镜。

  体验消费业态,既是热点,同时又具有消费频次高、人气旺的特点,与家居行业可以实现互补。

    “720”战队,居中者为赵筱  ■本专题策划  广州日报全媒体记者陈伟胜  ■本专题撰写  广州日报全媒体记者白志标  第2届WESG(世界电子竞技运动会)总决赛日前在海口落幕,这一届WESG最大的特点就是设置了女子组,而来自中国的LLG战队荣膺CS:GO亚军,成了唯一进入前三的中国女子参赛队。“新华视点”“新浪科技”也凭借在上周的精彩表现以大幅进步进入前20。

  为提高社会保险资金征管效率,将基本养老保险费、基本医疗保险费、失业保险费等各项社会保险费交由税务部门统一征收。

  百度  在智能家居的产品探讨上基本没有涉及,也可以看出不管是生产者还是使用者,对于目前停留在表面所谓的智能家居概念是有怀疑的。

  龙新(责编:隋尚君(实习生)、蒋琪)”广西柳州市市长吴炜说,2017年引导社会固定资产在工业机器人方面投资亿元,为企业降低成本30%,节约人工40%,提高效率30%。

  百度 百度 百度

  hp1008打印机驱动(惠普1008驱动下载) 官方版

 
责编:

ThinkPHP 框架SQL注入技术分析

2018-05-27 156184人围观 ,发现 1 个不明物体 WEB安全

4月12号,ThinkPHP官方团队发布“ThinkPHP5.0.17&5.1.9版本发布——包含安全更新”通知,提醒用户第一时间更新框架版本,在这次更新中,包含了对由360企业安全集团代码卫士团队报送的一个高危安全漏洞的修复。本文针对该漏洞的技术细节进行分析。 

简要描述

ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生的12年间一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。目前ThinkPHP框架是国内使用量最大的框架之一,国内用户量众多。

近日,360企业安全集团代码卫士团队安全研究人员发现该框架V5.1.7-V5.1.8 版本在底层数据处理驱动解析数据的时候存在缺陷,一定场景下,攻击者可以通过构造恶意数据包利用SQL注入的方式获取用户数据库内容。360企业安全集团代码卫士团队已第一时间和ThinkPHP团队进行沟通修复,建议相关用户及时更新官方发布的新版本。

漏洞分析

注:该漏洞ThinkPHP官方团队在报送当天(2018-05-27)紧急进行了修复处理,详细请参考:https://github.com/top-think/framework/commit/39bb0fe6d50ee77e0779f646b10bce08c442a5e3

以下漏洞分析基于ThinkPHP V5.1.8(2018-05-27未更新版)

这里我们主要跟进分析执行update操作的过程。为了方便理解,先直接放出函数的调用栈。

Mysql.php :200, think\db\builder\Mysql-> parseArrayData()

Builder.php :147, think\db\Builder-> parseData()

Builder.php :1139, think\db\Builder-> update()

Connection.php :1149, think\db\Connection-> update()

Query.php :2571, think\db\Query-> update()

Index.php :18, app\index\controller\Index-> testsql()

Container.php :285, ReflectionMethod ->invokeArgs()

Container.php :285, think\Container-> invokeReflectMethod()

Module.php :139, think\route\dispatch\Module-> run()

Url.php :31, think\route\dispatch\Url-> run()

App.php :378, think\App-> think\{closure}()

Middleware.php :119, call_user_func_array:{ C:\wamp64\www\think518\thinkphp\library\think\Middleware. php:119}()

Middleware.php :119, think\Middleware-> think\{closure}()

Middleware.php :74, call_user_func:{ C:\wamp64\www\think518\thinkphp\library\think\Middleware. php:74}()

Middleware.php :74, think\Middleware-> dispatch()

App.php :399, think\App-> run()

index.php :21, { main}()

缺陷关键点为thinkphp解析用户传递过来的Data可控,且可以绕过安全检查。

根据文件 Connection.php:1149,think\db\Connection->update()第1102行update函数分析,这个函数的主要功能是用于执行update SQL语句。

//Connection.php:1149, think\db\Connection->update()

public function update(Query $query)

   {

       $options = $query->getOptions();


       if (isset($options ['cache']) && is_string($options['cache' ]['key'])) {

           $key = $options['cache']['key' ];                    

       }


       $pk   = $query->getPk($options );                    

       $data = $options['data'];


       if (empty($options ['where'])) {

           // 如果存在主键数据 则自动作为更新条件

           if (is_string($pk ) && isset( $data[$pk])) {                            

               $where[ $pk] = [$pk, '=' , $data[$pk]];

               if (!isset($key )) {

                   $key = $this->getCacheKey($query , $data[$pk]);

               }

               unset( $data[$pk]);

           } elseif (is_array($pk )) {

               // 增加复合主键支持

               foreach ($pk as $field ) {

                   if (isset($data [$field])) {

                       $where [$field] = [$field, '=', $data[$field ]];                            

                   } else {

                       // 如果缺少复合主键数据则不执行

                       throw new Exception( 'miss complex primary data');

                   }

                   unset( $data[$field]);

               }

           }


           if (!isset($where )) {

               // 如果没有任何更新条件则不执行

               throw new Exception( 'miss update condition');

           } else {

               $options[ 'where']['AND'] = $where;

               $query-> setOption('where', ['AND' => $where ]);                        

           }

       } elseif (!isset($key ) && is_string( $pk) && isset ($options['where'][ 'AND'][$pk])) {                                    

           $key = $this->getCacheKey($query , $options['where'][ 'AND'][$pk]);

       }


       // 更新数据

       $query-> setOption('data', $data );                    


       // 生成UPDATE SQL语句

       $sql  = $this->builder->update ($query);

       $bind = $query->getBind();


       if (!empty($options ['fetch_sql'])) {

           // 获取实际执行的SQL语句

           return $this->getRealSql($sql , $bind);

       }


       // 检测缓存

       $cache = Container::get( 'cache');


       if (isset($key ) && $cache-> get($key)) {                            

           // 删除缓存

           $cache-> rm($key);

       } elseif (!empty($options ['cache']['tag'])) {

           $cache-> clear($options['cache' ]['tag']);

       }


       // 执行操作

       $result = '' == $sql ? 0 : $this->execute($sql , $bind);


       if ($result) {                    

           if (is_string($pk ) && isset( $where[$pk])) {                            

               $data[ $pk] = $where [$pk];

           } elseif (is_string($pk ) && isset( $key) && strpos ($key, '|' )) {

               list( $a, $val) = explode('|', $key);

               $data[ $pk]     = $val ;                    

           }


           $query-> setOption('data', $data );                    

           $query-> trigger('after_update');

       }


       return $result;

   }

第1146行, $query->setOption(‘data’,$data);这里将用户传递的 $dataset到 $query变量中,为下一步的生成 UPDATE SQL语句做准备,执行 $sql=$this->builder->update($query);语句,重点马上要来了,跟进 Builder.php:1139,think\db\Builder->update()函数

//Builder.php:1139, think\db\Builder->update()

public function update(Query $query)

   {

       $options = $query->getOptions();


       $table = $this->parseTable($query , $options['table']);

       $data  = $this->parseData($query , $options['data']);


       if (empty($data )) {

           return '';

       }


       foreach ($data as $key => $val) {

           $set[] = $key . ' = ' . $val;

       }


       return str_replace(

           [ '%TABLE%', '%SET%', '%JOIN%', '%WHERE%' , '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'],

           [

               $this-> parseTable($query, $options ['table']),

               implode( ' , ', $set),

               $this-> parseJoin($query, $options ['join']),

               $this-> parseWhere($query, $options ['where']),

               $this-> parseOrder($query, $options ['order']),

               $this-> parseLimit($query, $options ['limit']),

               $this-> parseLock($query, $options ['lock']),

               $this-> parseComment($query, $options ['comment']),

           ],

           $this-> updateSql);

   }

刚刚我们将用户可控的 $dataset到 $query['options']中,这里我们先获取 $query['options']内容到  $options中,然后对Data进行解析 $data=$this->parseData($query,$options['data']);

//Builder.php:147, think\db\Builder->parseData()

protected function parseData(Query $query, $data = [], $fields = [], $bind = [], $suffix = '')

   {

       if (empty($data )) {

           return [];

       }


       $options = $query->getOptions();


       // 获取绑定信息

       if (empty($bind )) {

           $bind = $this->connection->getFieldsBind ($options['table']);

       }


       if (empty($fields )) {

           if ('*' == $options['field']) {                        

               $fields = array_keys($bind);

           } else {

               $fields = $options['field'];

           }

       }


       $result = [];


       foreach ($data as $key => $val) {

           $item = $this->parseKey($query , $key);


           if ($val instanceof Expression) {

               $result[ $item] = $val ->getValue();

               continue ;                

           } elseif (!is_scalar($val ) && ( in_array($key, (array) $query-> getOptions('json')) || 'json' == $this->connection-> getFieldsType($options[ 'table'], $key))) {

               $val = json_encode($val);

           } elseif (is_object($val ) && method_exists( $val, '__toString')) {

               // 对象数据写入

               $val = $val->__toString();

           }


           if (false !== strpos($key, '->')) {

               list( $key, $name) = explode('->', $key);

               $item             = $this->parseKey( $query, $key);

               $result[ $item]    = 'json_set(' . $item . ', \'$.' . $name . '\', ' . $this->parseDataBind( $query, $key, $val , $bind, $suffix ) . ')' ;                                                

           } elseif (false === strpos($key, '.') && !in_array($key, $fields, true)) {

               if ($options['strict' ]) {

                   throw new Exception( 'fields not exists:[' . $key . ']');

               }

           } elseif (is_null($val )) {

               $result[ $item] = 'NULL';

           } elseif (is_array($val ) && ! empty($val)) {                            

               switch ($val[0 ]) {

                   case 'INC':

                       $result [$item] = $item . ' + ' . floatval($val[ 1]);

                       break ;                

                   case 'DEC':

                       $result [$item] = $item . ' - ' . floatval($val[ 1]);

                       break ;                

                   default :                

                       $value = $this->parseArrayData( $query, $val);

                       if ($value) {                    

                           $result [$item] = $value;

                       }

               }

           } elseif (is_scalar($val )) {

               // 过滤非标量数据

               $result[ $item] = $this ->parseDataBind($query, $key, $val, $bind , $suffix);

           }

       }


       return $result;

   }

在第115行,通过 foreach($dataas$key=>$val)处理 $data,然后解析 $key保存到  $item变量中去,之后执行下面的判断逻辑,想要合理地进入各个判断分支,就要巧妙的构造 $key和 $value也就是 $data的值。紧接着我们进入漏洞触发点  $value=$this->parseArrayData($query,$val);,跟进函数 $value=$this->parseArrayData($query,$val);

//Mysql.php:200, think\db\builder\Mysql->parseArrayData()

protected function parseArrayData(Query $query, $data)

   {

       list($type, $value) = $data;

       switch (strtolower($type)) {

           case 'point':

               $fun   = isset($data[2]) ? $data[2] : 'GeomFromText';

               $point = isset($data[3]) ? $data[3] : 'POINT';

               if (is_array($value)) {

                   $value = implode(' ', $value);

               }

               $result = $fun . '(\'' . $point . '(' . $value . ')\')';//需要简单的构造一下sql语句

               break;

           default:

               $result = false;

       }

       return $result;

   }

这里 $type、 $value和 $data均为可控值,那么函数返回的 $result也就是可控的。回到上一个  Builder.php文件中,将返回的结果赋值到 $result[$item]=$value;中,之后的生成SQL语句和常见的流程没有任何差别不再展开具体分析。

验证截图

验证截图.jpg

修复建议

更新受影响ThinkPHP版本到最新版本

参考

ThinkPHP5.0.17&5.1.9版本发布——包含安全更新

http://www.thinkphp.cn.maroc-canada.com/topic/55757.html

*本文作者:360代码卫士,转载请注明来自FreeBuf.COM

发表评论

已有 1 条评论

取消
Loading...
css.php 百度