命令注入(Command Injection)是指通過提交惡意構造的參數破壞命令語句結構。從而達到執行惡意命令的目的。
查看命令注入的流程:
1;查看是否調用系統命令。
2;函數以及函數的參數是否可控。
3;是否拼接命令注入。
下面我們使用dvwa來做測試。
A;我們先將安全等級調整為“low”
1;查看源代碼
<?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $target = $_REQUEST[ 'ip' ]; // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "<pre>{$cmd}</pre>"; } ?>
2;代碼分析:
核心函數shell_exec(),該函數的功能就是通過shell執行命令並將完整輸出作為字符串返回。整個代碼看下來並沒有對輸入的參數做一些過濾。幾乎可以判定存在命令注入的漏洞。
3;漏洞利用:
使用&&來執行多條命令(Window和linux都可以使用)輸入命令“127.0.0.1 && ifconfig ”這個時候我們發現ifconfig 命令也成功被執行且返回效果。
B;下面我們將安全等級調整為“Medium”
1;查看代碼
<?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $target = $_REQUEST[ 'ip' ]; // Set blacklist $substitutions = array( '&&' => '', ';' => '', ); // Remove any of the charactars in the array (blacklist). $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "<pre>{$cmd}</pre>"; } ?>
2;代碼分析:
這里我們發現代碼中采用了黑名單的方法過濾了字符串“&&”,“;”也就說類似於127.0.0.1 && ifconfg 這樣使用被過濾的連接符號就無法在成功執行。
我們都知道,采用黑名單並不是絕對安全的,比如上面代碼當中就沒有過濾“&”那么下面我們就可以利用這點。
3;漏洞利用:
輸入127.0.0.1 & ifconfig
C;安全等級“High”
1;分析代碼,這里我們可以看到只是補充了黑名單。黑名單在過濾的過程中一般會出現遺漏關鍵字的問題。另外就是關鍵字過濾不當的問題。比如下面代碼我們發現黑名單當中'| ' 這么符號的過濾,我們仔細發現后面有一個空格,也就是說如果我們輸入的參數管道符不帶空格,代碼就無法匹配到。
<?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $target = trim($_REQUEST[ 'ip' ]); // Set blacklist $substitutions = array( '&' => '', ';' => '', '| ' => '', '-' => '', '$' => '', '(' => '', ')' => '', '`' => '', '||' => '', ); // Remove any of the charactars in the array (blacklist). $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "<pre>{$cmd}</pre>"; } ?>
2;漏洞利用:
注入代碼:127.0.0.1|ifconfig 我們可以發現命令ifconfig可以被成功執行。
C;Impossible
1;查看代碼
<?php if( isset( $_POST[ 'Submit' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input $target = $_REQUEST[ 'ip' ]; $target = stripslashes( $target ); // Split the IP into 4 octects $octet = explode( ".", $target ); // Check IF each octet is an integer if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) { // If all 4 octets are int's put the IP back together. $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3]; // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "<pre>{$cmd}</pre>"; } else { // Ops. Let the user name theres a mistake echo '<pre>ERROR: You have entered an invalid IP.</pre>'; } } // Generate Anti-CSRF token generateSessionToken(); ?>
2;代碼分析:
這段代碼一共進行了兩點防護,第一是對token進行了驗證。第二對輸入數據進行了嚴格的限定(這里功能是執行PING命令。所以嚴格設定了輸入形式為IP 的形式)
注釋:token可以預防csrf的攻擊。預防原理是
1;當客戶端請求頁面時,服務器會生成一個隨機數Token,並且將Token放置到session當中。然后將Token發給客戶端(一般通過構造hidden表單)
2; 客戶端提交請求時,Token會隨着表單一起提交到服務器端。
然后,如果應用於"anti csrf攻擊",則服務器端會對Token值進行驗證,判斷是否和session中的Token值相等,若相等,則可以證明請求有效,不是偽造的。