代碼執行
代碼執行是指應用程序本身過濾不嚴,當應用在調用一些字符串函數的時候用戶可以通過請求將代碼注入到應用中執行。
存在於eval()、assert()、preg_replace()、call_user_func()、array_map()以及動態函數中,很難通過黑盒測試查找。
挖掘思路
1:用戶能夠控制函數輸入
2:存在可執行的危險函數
常見危險函數
1、eval和assert
這倆兩個函數原本作用就是動態執行代碼,所以他們的參數直接就是PHP代碼
<?php if(isset($_REQUEST['cmd'])){ $cmd = ($_REQUEST["cmd"]); system($cmd);//eval($cmd); echo "</pre>$cmd<pre>"; die; } ?>
因爲對傳入沒有過濾,所以直接傳入PHP代碼
?cmd=phpinfo();
2、preg_replace函數
對字符串進行正則處理,一般挖掘的時候是都是繞過正則的
<?php preg_replace("/\[(.*)\]/e",'\\1',$_GET['str']); ?>
第一組是匹配中括號的的內容,\\1作爲第一組的結果填充,這裏是直接執行代碼,所以
?str=[phpinfo()]
就能直接執行phpinfo()
3、回調函數
call_user_func()和array_map()等都有調用其他函數的功能,過濾不嚴且傳入參數可控,就可以調用函數來執行代碼
<?php $b="phpinfo()"; call_user_func($_GET['a'],$b); ?>
當傳入assert函數的時候,就可以執行phpinf()
?a=assert
4、動態函數執行(重點)
因爲PHP的特性,PHP函數可以由字符串拼接,我們可以用一個變量名去代替一個函數
<?php $_GET['a']{$_GET['b']}; ?>
接受a的參數作爲函數,b的爲函數的參數,所以傳入
?a=assert&b=phpinfo()
就會打印PHP的信息
修復
1、儘量不要執行外部的應用程序或命令
2、使用自定義函數或函數庫來替代外部應用程序或命令的功能
3、使用escappeshellarg函數來處理命令的參數
4、使用sare_mode_exec_dir來指定可執行的文件路徑
5、將執行的參數做白名單限制,在代碼或配置文件中限制某些參數