Command Injection,即命令注入,是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一,国内著名的Web应用程序Discuz!、DedeCMS等都曾经存在过该类型漏洞。
Command Execution命令执行漏洞的产生原因一般就是将用户输入未经过滤或者过滤不严就直接当作系统命令进行执行,通过批处理技巧来一次执行多条命令,这样就可以执行任意命令。
在命令执行中,常用的连接符号有四个:&& & || | ;
&&:先执行前一个指令,执行成功后,继续执行后面的指令
||:先执行前一个指令,执行失败后,再执行后一个指令
&:用于直接连接后面的多条指令
|:管道符,将前面的命令执行结果,作为后一条命令的参数输入
;:用于连接多个命令
1、首先打开dvwa的command Execution
2、在view source下观察三种不同安全级别的代码,可以发现如下信息。
Low Command Execution Source
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 '
'.$cmd.'
';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo ''.$cmd.'
';
}
}
?>
low级别中,简单的阅读代码后发现,该代码的含义为输入IP地址,后台执行ping命令。此处有一个PHP函数。
isset()检测变量是否已设置并且非 NULL.(
http://php.net/manual/zh/function.isset.php)
stristr() 的功能是搜索字符串在另一字符串中的第一次出现。(http://www.w3school.com.cn/php/func_string_stristr.asp)
shell_exec的功能是通过shell执行命令并将输出结果作为字符串输出。用在此处即将target用ping执行并返回结果字符串。(http://php.net/manual/en/function.shell-exec.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 '
'.$cmd.'
';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo ''.$cmd.'
';
}
}
?>
medium级别的代码和low级别的相比的区别是创建了一个数组,并将一些字符放在这个数组中,当发现这个目标中包含所有键名的新数组时,用$substitutions代替。即过滤掉上述的字符。本质上采用的是黑名单机制,因此依旧存在安全问题。
array()创建数组。(http://www.w3school.com.cn/php/php_ref_array.asp)
str_replace() 函数以其他字符替换字符串中的一些字符(区分大小写)。(http://www.w3school.com.cn/php/func_string_str_replace.asp)str_replace(find,replace,string,count) 其中find,replace,string是必须的,count可选。最后返回带有替换值的数组或字符串。
array_keys()
返回包含数组中所有键名的一个新数组。(http://www.w3school.com.cn/php/func_array_keys.asp)
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 '
'.$cmd.'
';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo ''.$cmd.'
';
}
}
else {
echo 'ERROR: You have entered an invalid IP
';
}
}
?>
high级别的代码和medium相比较则是将输入的东西严格控制,首先去反斜杠,再将IP地址以点号打散为数组,判断数组中的是否均为数字,均为数字则执行下一步。
stripslashes() 函数删除由 addslashes() 函数添加的反斜杠(http://www.w3school.com.cn/php/func_string_stripslashes.asp)
explode() 函数把字符串打散为数组。(http://www.w3school.com.cn/php/func_string_explode.asp)
is_numeric() 函数用于检测变量是否为数字或数字字符串。(http://www.runoob.com/php/php-is_numeric-function.html)
3、对该命令行执行进行测试。
首先调整安全级别到low,输入192.168.22.128得到以下结果
输入192.168.22.128&&whoami 得到以下结果。同理其他命令
有此可见该漏洞的危害。
调整安全级别到medium级别,输入192.168.22.128得到结果
输入192.168.22.128|whoami,得到结果,同理其他命令。由此可见medium没有拉入黑名单的其他字符还是可以继续使用的,也是较不安全。
调整安全级别到high级别,输入192.168.22.128,则得到以下结果。
输入192.168.22.128&&whoami结果,试了好几次都很安全,自己查了下这种写法很安全。也可能是靶机版本的原因我的high级别的command Execution 中的high级别的源码是这样的。我看了别人的发现他们的high级别的源码和我的medium相似,即通过设置黑名单的方式,将字符过滤掉,这种类型只要有漏掉的没有过虑的字符就可以进行注入。