命令注入
命令:这个命令指的是操作系统的命令。
命令注入:就是通过web程序,在服务器上拼接系统的命令。有些网站对这些有需求,就开放了这些功能,但是,没有对命令进行严格的过滤,从而导致命令注入漏洞。
命令注入的条件
1、web应用程序调用可执行系统命令的函数。
2、执行系统命令函数或者函数的参数可控,如果它把你填入的参数限制得死死得,那也没办法用命令注入了。
3、参数可控,而且可拼接,一般命令注入的情况就是,前面语句固定的,后面需要我们自己去拼接语句,如果说遇到的情况不可拼接的话,那只能想别的办法了。
DVWA的命令注入漏洞
一、low安全级别
ok,关于ping命令我这里就不说了,从以前的Linux都继承下来了,现在windows上也有。从上图,我们可以看到,ping本地是能ping通的,我们就可以用命令连接符连接试试。
可以看到,我们通过&&连接两个命令,达到了注入的目的,在这里,我尝试了一下创建用户命令,不知道是权限不够还是什么情况,好像没有成功。我们先来看看服务器端的核心源码。
<?php
if( isset( $_POST[ 'submit' ] ) ) {
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
?>
它只是判断了一下操作系统,并没有对传入的ip参数进行过滤,直接传到后台执行了。这明显很致命。
二、medium安全级别
这里,我输入同样的命令后,它没有任何响应,看来它可能在low的基础上设置了过滤,我们再看能不能ping通IP。
能ping通,说明漏洞可能还在,它只是设置了过滤。ok,现在,我们换用其他命令连接符:
ok,我们换用其它命令连接符绕过它的过滤了,现在看看服务器端的核心源码。
<?php
if( isset( $_POST[ 'submit'] ) ) {
$target = $_REQUEST[ 'ip' ];
// Remove any of the charactars in the array (blacklist).
$substitutions = array(
'&&' => '',
';' => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
?>
很明显,代码量多了,多的部分多在哪儿?它在low的基础上,还做了简单的符号过滤把&&和;替换成空了。这样就出现语法错误,直接就把整个输入的命令过滤了。
三、high安全级别
我一般都这样,还是先ping一下某个IP,看这个功能有没有关,有时候,它一个功能不一定随时开着。
能ping通,看来有搞头,一般的升级,是在上一个的基础上升级的,我测试&&后无效,就直接测试&连接符。
它提示我,说我输入的IP不合法,无效。这次它过滤了&符,我们再看看它是否过滤了管道’|‘或者’||’。
ok,还是绕不过去,我都试过了,然后,我们看服务器后端源代码。
<?php
if( isset( $_POST[ 'submit' ] ) ) {
$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')) {
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
else {
echo '<pre>ERROR: You have entered an invalid IP</pre>';
}
}
?>
这个它对IP进行了严格的筛选,它对IP的每一个部分都筛选了,只允许输入的IP中包含数字和点,做到这样的话,目前几乎是没有漏洞了。
总结这几个安全级别漏洞并审计
做到这,先小结一下,第一个是没有加过滤,这对于服务器来说危险程度是比较高的。第二个安全等级,主要是通过黑名单机制来进行限制,这种方法并不妥当。因为,黑名单中的字符毕竟有限,不能百分百保证能过滤所有危险。它只能在它黑名单的范围内起作用,在做命令过滤的时候,明显是不够专业的。
漏洞解决方法
现在,说一下解决办法,在DAVWA中,它是严格限制了IP的每一个元素,基本是没有漏洞了。然后,现在我也想不到啥好的办法,如果说用黑名单机制,还不如直接严格限制来的快,而且直接严格限制相比黑名单机制更加安全。如果说还能进一步完善的话,我觉得可以在后面的代码中记录一下输入特殊符号的用户IP,监视这个IP或者提交到waf的禁封策略。