DVWA通关挑战之命令注入,做起来其实挺简单,主要是看一下代码,学习一下思路。
DVWA通关之命令注入(command injection)难度等级:low
过关思路
- 我们先将其难度设置为low,看到其界面如下:
- 通过分析得知,该功能是输入一个IP地址,然后通过ping进行测试,先输入127.0.0.1和www.baidu.com测试如下:
127.0.0.1
www.baidu.com
- 可以看到,IP地址和域名都是能够ping通的,接下来就是使用命令拼接测试了,
输入127.0.0.1 | whoami
命令注入成功。
- 命令汇总,经过测试,以下命令均可注入成功。
127.0.0.1|whoami
127.0.0.1&whoami
127.0.0.1000 || whoami
127.0.0.1 && whoami
注意:有空格和无空格有时会有意想不到的效果
做完了当然得看一下源码:
可以看到,该代码没有对用户的输入做任何的过滤,直接使用shell_exec函数执行用户输入,这是非常危险的。
难度等级:medium
过关思路
- 这里过关思路和low一致,也没啥可说的,我们主要看一下源码就行。
- 源代码如下:
通过分析,可以看出,medium关卡比low关卡多了一个黑名单。其通过数组的方式将&&和;进行了过滤,即将其替换为空。但是,这种过滤基本上还是跟没有过滤差不多,因为黑名单里的过滤太少了,黑名单也不安全。
难度等级:high
过关思路
- 上手先测试几个前面的payload,发下好多都被过滤了,但是还有几个可以用:
127.0.0.1 || whoami
127.0.0.1|whoami
127.0.0.1000||whoami
- 我们直接看源代码:
可以看到,这次的黑名单过滤明显的多了起来,但是也发现(可能是故意给我们漏出来的?),其在过滤的时候,没有过滤|而是过滤了|+空格,所以,该代码只是遇到单单一个|,不会进行过滤。
难度等级: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(); ?>
一波代码审计,我们发现,这次的过滤和前面的两关没有任何相似之处,而是直接换了一种思路,也就是我们所说的白名单。其控制了用户的输入,不在控制用户的输入哪些不能用,而是控制用户的输入哪些能用。
- 我们还是慢慢从函数入手分析:
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
这段代码是控制了用户身份信息,在每次和服务器交互之时,服务器会随机给用户分配一个ID,用作用户的身份凭证,这样也就断绝了假冒用户的事件发生。
$target = stripslashes( $target );
stripslashes函数用于删除输入中的反斜杠。
$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 ))
而这段代码是控制了用户只能输入IP地址,无法使用域名。且在用户输入IP地址后,使用explode函数以.为分割,将IP地址分割为数组,最后判断数组的个数是否为4。可以说,过滤确实很绝,但是也有一个不好之处就是屏蔽掉了域名。
总结
- 掌握有关命令执行的知识 windows 或 linux 下:
命令执行漏洞(| || & && 称为管道符)
command1 && command2 先执行 command1,如果为真,再执行 command2
command1 | command2 只执行 command2
command1 & command2 先执行 command2 后执行 command1
command1 || command2 先执行 command1,如果为假,再执行 command2
windows:(1)|(2)||(3)&(4)&&
linux:(1)|(2)||(3);(4)&&
- 命令注入的相关系统函数:
① system()
② exec()
③ shell_exec()
④ passthru()
⑤ popen()
⑥ ``(反引号)