命令執行漏洞,用戶通過瀏覽器在遠程服務器上執行任意系統命令,嚴格意義上,與代碼執行漏洞還是有一定的區別。
0x01漏洞實例
例1:
<?php $target=$_REQUEST['ip']; $cmd = shell_exec('ping '.$target); echo "<pre>{$cmd}</pre>"; ?>
提交 http://127.0.0.1/cmd.php?ip=|net user
提交以后,命令變成了 shell_exec('ping '.|net user)
0x02 常用命令執行函數
exec()、system()、popen()、passthru()、proc_open()、pcntl_exec()、shell_exec() 、反引號` 實際上是使用shell_exec()函數
system() 輸出並返回最后一行shell結果。
exec() 不輸出結果,返回最后一行shell結果,所有結果可以保存到一個返回的數組里面。
passthru() 只調用命令,把命令的運行結果原樣地直接輸出到標准輸出設備上。
popen()、proc_open() 不會直接返回執行結果,而是返回一個文件指針
<?php #system('net user'); #passthru ('dir'); #echo exec('whoami'); #echo shell_exec('whoami'); #echo `whoami`; ?>
0x03 漏洞利用及繞過姿勢
| 命令管道符
<>>> 文件重定向符
測試: 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
0x04 如何防止命令執行漏洞
PHP內置的兩個函數可以有效防止命令執行:
escapeshellarg() 將給字符串增加一個單引號並且能引用或者轉碼任何已經存在的單引號,這樣以確保能夠直接將一個字符串傳入 shell 函數,並且還是確保安全的。對於用戶輸入的部分參數就應該使用這個函數。資料參考:http://cn.php.net/manual/zh/function.escapeshellarg.php
escapeshellcmd() 對字符串中可能會欺騙 shell 命令執行任意命令的字符進行轉義。 此函數保證用戶輸入的數據在傳送到 exec() 或 system() 函數,或者 執行操作符 之前進行轉義。資料參考:http://cn.php.net/manual/zh/function.escapeshellcmd.php
當然,修復方法還有很多方式,修復方式一般有兩種思維:
1、黑名單:過濾特殊字符或替換字符 2、白名單:只允許特殊輸入的類型/長度
修復代碼示例一:
<?php $target=$_REQUEST['ip']; $octet = explode( ".", $target ); if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) { $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3]; $cmd = shell_exec('ping '.$target); echo "<pre>{$cmd}</pre>"; } else { echo '<pre>ERROR: You have entered an invalid IP.</pre>'; } ?>
修復代碼示例二:
<?php $target=$_REQUEST['ip']; $cmd = shell_exec('ping '. escapeshellcmd($target)); echo "<pre>{$cmd}</pre>"; ?>
最后
歡迎關注個人微信公眾號:Bypass--,每周原創一篇技術干貨。
參考文章:
命令執行漏洞 http://www.jianshu.com/p/1e706f13b088