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进行了严格的限制,只有诸如“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。这个确实已经结合业务场景来进行约束了。