In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
How to carry out ThinkPHP framework SQL injection, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain for you in detail, people with this need can come to learn, I hope you can get something.
Brief description
ThinkPHP is a free and open source, fast, simple, object-oriented lightweight PHP development framework, which was born for agile WEB application development and simplifying enterprise application development. ThinkPHP has been adhering to simple and practical design principles in the 12 years since its birth, focusing on ease of use while maintaining excellent performance and minimalist code. At present, ThinkPHP framework is one of the most widely used frameworks in China, with a large number of domestic users.
Recently, security researchers of the Code Guardian team of 360Enterprise Security Group have found that the V5.1.7-V5.1.8 version of the framework has defects in the underlying data processing driver when parsing data. In certain scenarios, attackers can construct malicious packets and use SQL injection to obtain user database content. The Code Guardian team of the Enterprise Security Group has immediately communicated with the ThinkPHP team to fix it, and it is recommended that the relevant users update the official version in time.
Loophole analysis
Note: the ThinkPHP official team urgently fixed the vulnerability on the same day (2018-04-06). For more information, please refer to https://github.com/top-think/framework/commit/39bb0fe6d50ee77e0779f646b10bce08c442a5e3
The following vulnerability analysis is based on ThinkPHP V5.1.8 (2018-04-05 not updated)
Here we mainly follow up and analyze the process of performing update operations. To make it easier to understand, first release the function's call stack directly.
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, Container.php\ think > think () 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} ()
The key point of the defect is that thinkphp parses the Data passed by the user is controllable, and can bypass the security check.
According to the analysis of the update function in line 1102 of the file Connection.php:1149,think\ db\ Connection- > update (), the main function of this function is to execute update SQL statements.
/ / 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'];} $Competition = $query- > getPk ($options) $data = $options ['data'] If (empty ($options ['where']) {/ / if primary key data exists, automatically as update condition if (is_string ($Competition) & & isset ($data [$Competition]) {$where [$Competition] = [$Competition,' =', $data [$Competition]] If (! isset ($key)) {$key = $this- > getCacheKey ($query, $data [$Competition]);} unset ($data [$Competition]) } elseif (is_array ($competitive)) {/ / add composite primary key support foreach ($competitive as $field) {if (isset ($data [$field])) {$where [$field] = [$field,'=', $data [$field]] } else {/ / do not execute throw new Exception ('miss complex primary data') if compound primary key data is missing;} unset ($data [$field]) }} if (! isset ($where)) {/ / do not execute throw new Exception ('miss update condition') if there are no update conditions;} else {$options [' where'] ['AND'] = $where; $query- > setOption (' where', ['AND' = > $where]) }} elseif (! isset ($key) & & is_string ($Competition) & & isset ($options ['where'] [' AND'] [$Competition]) {$key = $this- > getCacheKey ($query, $options ['where'] [' AND'] [$Competition]) } / / Update data $query- > setOption ('data', $data); / / generate UPDATE SQL statements $sql = $this- > builder- > update ($query); $bind = $query- > getBind () If (! empty ($options ['fetch_sql']) {/ / get the actually executed SQL statement return $this- > getRealSql ($sql, $bind);} / / detect cache $cache = Container::get (' cache') If (isset ($key) & & $cache- > get ($key)) {/ / remove cache $cache- > rm ($key);} elseif (! empty ($options ['cache'] [' tag'])) {$cache- > clear ($options ['cache'] [' tag']) } / / execute operation $result ='= $sql? 0: $this- > execute ($sql, $bind); if ($result) {if (is_string ($Competition) & & isset ($where [$Competition]) {$data [$Competition] = $where [$Competition] } elseif (is_string ($Competition) & & isset ($key) & & strpos ($key,'|') {list ($a, $val) = explode ('|', $key); $data [$Competition] = $val;} $query- > setOption ('data', $data) $query- > trigger ('after_update');} return $result;}
Line 1146, $query- > setOption ('data',$data); here, put the $dataset passed by the user into the $query variable to prepare for the next generation of the UPDATE SQL statement, execute $sql=$this- > builder- > update ($query); statement, the focus is coming, follow up the Builder.php:1139,think\ db\ Builder- > update () function
/ / 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) }
Just now we put the user-controllable $dataset into $query ['options']. Here we first get the content of $query [' options'] to $options, and then parse the 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 (); / / get binding information 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')) {/ / object data is written to $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)) {/ / filter non-scalar data $result [$item] = $this-> parseDataBind ($query, $key, $val, $bind, $suffix);}} return $result;}
In line 115, you process $data through foreach ($dataas$key= > $val), then parse $key and save it in the $item variable, and then execute the following judgment logic. If you want to enter each judgment branch reasonably, you have to cleverly construct the values of $key and $value, which are the values of $data. Immediately after we enter the vulnerability trigger point $value=$this- > parseArrayData ($query,$val);, follow up the function $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. ')\)'; / / you need to simply construct the sql statement break; default: $result = false;} return $result;}
Where $type, $value, and $data are all controllable values, then the $result returned by the function is also controllable. Go back to the previous Builder.php file, assign the returned result to $result [$item] = $value;, and then generate the SQL statement without any difference from the common process without further analysis.
Verify the screenshot
Repair suggestion
Update affected ThinkPHP version to latest version
Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.