Command Injection
Command Injection,即命令注入,是指通過提交惡意構造的參數破壞命令語句結構,從而達到執行惡意命令的目的。PHP命令注入攻擊漏洞是PHP應用程序中常見的腳本漏洞之一。
PHP命令注入漏洞的函數 systme()、exec()、shell_exec()
注入命令過程中,常常需要使用一些系統命令的拼接方式,以達到更多復雜功能的實現,尤其是存在限制的情況,運用好可用來繞過限制。
邏輯運算符::&&:代表首先執行命令a,若成功再執行命令b,又被稱為短路運算符。&:代表首先執行命令a再執行命令b,不管a是否成功,都會執行命令b。在執行效率上來說“&&”更加高效。||:代表首先執行a命令再執行b命令,只有a命令執行不成功,才會執行b命令。|:代表首先執行a命令,在執行b命令,不管a命令成功與否,都會去執行b命令。(當第一條命令失敗時,它仍然會執行第二條命令,表示A命令語句的輸出,作為B命令語句的輸入執行。)
LOW級別
輸入127.0.0.1,結果與在本機使用ping命令完全一致,說明這里可以讓我們執行ping命令。
分析源碼
可以看到這里直接將target 變量放入 shell_exec()
執行``ping`命令,沒有進行任何過濾,用戶端可以直接拼接特定的命令,來執行并獲取想要的信息。
<?phpif( 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 userecho "<pre>{$cmd}</pre>";
}?>
輸入一個命令拼接符號再加上需要執行的命令
查看IP地址 127.0.0.1&&ipconfig
Medium級別
輸入127.0.0.1,發現跟low等級顯示的一樣
查看源代碼,
<?phpif( isset( $_POST[ 'Submit' ] ) ) {// Get input$target = $_REQUEST[ 'ip' ];// Set blacklist$substitutions = array('&&' => '',';' => '',);// Remove any of the characters 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 userecho "<pre>{$cmd}</pre>";
}?>
發現在Low等級源碼的基礎上添加了一個黑名單,把‘&&’字符和‘;’字符過濾掉了,但我們可以使用黑名單之外的命令連接符命令注入
地址欄輸入127.0.0.1&ipconfig
High級別
觀察源代碼
<?phpif( isset( $_POST[ 'Submit' ] ) ) {// Get input$target = trim($_REQUEST[ 'ip' ]);// Set blacklist$substitutions = array('&' => '',';' => '','| ' => '','-' => '','$' => '','(' => '',')' => '','`' => '','||' => '',);// Remove any of the characters 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 userecho "<pre>{$cmd}</pre>";
}?>
發現過濾字符過濾得更多了。但仔細觀察發現有一個過濾是’| ‘,這個過濾是加了空格的,說明這個過濾其實是沒用的,只需要’|’后面直接加入參數,不保留空格,我們依然可以用這個命令連接符進行命令注入
地址欄輸入127.0.0.1|ipconfig
Impossible級別
<?phpif( isset( $_POST[ 'Submit' ] ) ) {// Check Anti-CSRF tokencheckToken( $_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 integerif( ( 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 userecho "<pre>{$cmd}</pre>";}else {// Ops. Let the user name theres a mistakeecho '<pre>ERROR: You have entered an invalid IP.</pre>';}
}// Generate Anti-CSRF token
generateSessionToken();?>
加入了Anti-CSRF token,同時對參數ip進行了嚴格的限制,只有諸如“數字.數字.數字.數字”的輸入才會被接收執行,因此不存在命令注入漏洞。這個確實已經結合業務場景來進行約束了。