命令行注入(Command Injection):
是指在某些需要输入数据的位置,还构造了恶意的代码破坏了原先的语句结构。而系统缺少有效的过滤,最终达到破坏数据、信息泄露甚至掌控电脑的目的。许多内容管理系统CMS存在命令注入漏洞。
命令连接符:
&&:代表首先执行命令a在执行命令b,但是前提条件是命令a执行正确才会执行命令b,在a执行失败的情况下不会执行b命令。所以又被称为短路运算符。
&:代表首先执行命令a在执行命令b,如果a执行失败,还是会继续执行命令b。也就是说命令b的执行不会受到命令a的干扰,在执行效率上来说“&&”更加高效。
||:代表首先执行a命令在执行b命令,如果a命令执行成功,就不会执行b命令,相反,如果a命令执行不成功,就会执行b命令。
|:代表首先执行a命令,在执行b命令,不管a命令成功与否,都会去执行b命令
解决乱码问题:
当我们输入文本时候后显示乱码,
在DVWA-master\dvwa\includes目录下找到dvwaPage.inc.php文件中所有的”charset=utf-8”,修改”charset=gb2312”,即可。
low级:
源代码:
<?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>"; } ?>
我们通过看源代码发现,没有进行任何过滤,我们只要使用“&&”、“&”、“|”即可完成注入。
1.使用ping 192.168.35.132&&dir,得到结果是(前面是我的主机地址)
2.使用ping 192.168.35.132&net user,得到结果是
3.使用ping 192.168.35.132|dir,192.168.35.132|net user得到结果是
Medium级:
源代码:
<?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>"; } ?>
我们通过观察代码发现,medium等级的命令行注入增加了一些过滤,通过查看源码可以看到,他将&&和:过滤成了空字符,所以我们依然可以进行注入。
输入”192.168.35.132 & dir”时,同样可以攻击,表明没有对”&”过滤。
但是”&&”和”&”是有区别的,”&&”是短路运算符,只有前一步执行成功才会执行后一步,而”&”则两个表达式都会执行。
我们输入”192.168.35.132&;& net view”时,也是可以的,因为过滤一次后相当于”192.168.35.132&& net view”。
还有很多方法可以进行命令行输入,比如:“|”、“||”等等
High级:
<?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>"; } ?>
这关看似没什么漏洞了,但是也是有一个小bug的。。引号下多了个空格,所以“|”还是可以用的。
Impossible级:
<?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(); ?>
可以看到,Impossible级别的代码加入了Anti-CSRF token,同时对参数ip进行了严格的限制,只有诸如“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。