什么是命令注入?
# 什么是命令注入?
命令注入就是在需要输入数据的地方输入了恶意代码,而且系统并没有对其进行过滤或者其他处理导致恶意代码也被执行,最终导致数据泄露或者正常数据被破坏。
# 常用到的命令
(总结来说就是系统操作命令 DOS 命令都可以在此执行试试)
ipconfig,net user(查看系统用户),dir(查看当前目录),find(查找包含指定字符的行),whoami(查看系统当前有效用户名)A&B(简单的拼接,AB 之间无制约关系),A&&B(A 执行成功才会执行 B),A|B(A 的输出作为 B 的输入),A||B(A 执行失败,然后才会执行 B)
# Low
# 分析
根据提示,我们先随便输入一个 IP 提交下试试。
下面出现了 PING 的过程
如果你熟悉 linux 的操作的话你一定知道有些语法可以让你在一行内运行多条命令:
;
分号,没有任何逻辑关系的连接符。当多个命令用分号连接时,各命令之间的执行成功与否彼此没有任何影响,都会一条一条执行下去。
||
逻辑或,当用此连接符连接多个命令时,前面的命令执行成功,则后面的命令不会执行。前面的命令执行失败,后面的命令才会执行。
&&
逻辑与,当用此连接符连接多个命令时,前面的命令执行成功,才会执行后面的命令,前面的命令执行失败,后面的命令不会执行,与 || 正好相反。
|
管道符,当用此连接符连接多个命令时,前面命令执行的正确输出,会交给后面的命令继续处理。若前面的命令执行失败,则会报错,若后面的命令无法处理前面命令的输出,也会报错。
我们使用任意一条构建 payload:
发现已经注入成功了..
# 查看源代码
点我展开 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { $target = $_REQUEST [ 'ip' ]; if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; } ?>
我们可以发现初级并没有使用任何字符过滤,这也就导致了命令注入的成功执行。。。
# Medium
我们直接使用刚才的 payload 试试:
竟然直接成功了。。。
我们看看源代码
点我展开 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { $target = $_REQUEST [ 'ip' ]; $substitutions = array ( '&&' => '' , ';' => '' , ); $target = str_replace ( array_keys ( $substitutions ), $substitutions , $target ); if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; } ?>
他只是单纯的加了 &&
和 ;
的过滤。。。
# High
按照惯例,我们继续使用老的 payload 试试:
并没有输出。。
我们直接看看源代码
点我展开 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { $target = trim ($_REQUEST [ 'ip' ]); $substitutions = array ( '&' => '' , ';' => '' , '| ' => '' , '-' => '' , '$' => '' , '(' => '' , ')' => '' , '`' => '' , '||' => '' , ); $target = str_replace ( array_keys ( $substitutions ), $substitutions , $target ); if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; } ?>
发现好多都被匹配到了,我们别慌
构造 payload
发现已经可以了。
为什么可以成功执行呢?
我们看看他匹配的部分,前后都没有空格,而我们构造的有空格,所以就没有匹配上。。。
# impossible
最后一关了,每每到这一关是不是心情大好,因为这一关就是告诉你怎么防御这些漏洞的。
点我展开 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { checkToken ( $_REQUEST [ 'user_token' ], $_SESSION [ 'session_token' ], 'index.php' ); $target = $_REQUEST [ 'ip' ]; $target = stripslashes ( $target ); $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 ]; if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; } else { echo '<pre>ERROR: You have entered an invalid IP.</pre>' ; } } generateSessionToken ();?>
查看源代码我们发现了问题
程序使用了正则匹配的方式来禁止输入其他字符,这样我们就没法使用 linux 命令的特性来攻击了。
同时也设置了 token,这个是用来防止 CSRF 的,后面我会提到。
至此,关于命令注入的就全部结束了,DVWA 上面确实很简单。