命令注入(Command Injection),对一些函数的参数没有做过滤或过滤不严导致的,可以执行系统或者应用指令(CMD命令或者bash命令)的一种注入攻击手段。PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一。
命令连接符
command1 && command2 "&&"表示先执行command1,执行成功后执行command 2,否则不执行command 2
command1 & command2 "&"表示先执行command 1,不管是否成功,都会执行command 2
command1 || command2 "||"表示先执行command1,执行失败后,执行command2
Low:
源码分析一下:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
//获取IP字段
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
//确定操作系统并执行ping命令
// stristr(string,search,before_search)
//stristr函数搜索字符串在另一字符串中的第一次出现,返回字符串的剩余部分(从匹配//点),如果未找到所搜索的字符串,则返回FALSE。参数string规定被搜索的字符串,参//数search规定要搜索的字符串(如果该参数是数字,则搜索匹配该数字对应的ASCII值//的字符),可选参数before_true为布尔型,默认为“false”,如果设置为“true”,函//数将返回search参数第一次出现之前的字符串部分。
// php_uname(mode)
//这个函数会返回运行php的操作系统的相关描述,参数mode可取值”a” (此为默认,包//含序列”s n r v m”里的所有模式),”s ”(返回操作系统名称),”n”(返回主机名),” //r”(返回版本名称),”v”(返回版本信息), ”m”(返回机器类型)。
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>";
}
?>
输入一个地址发现可以进行ping命令;
在没有什么过滤的情况下可以直接使用 :127.0.0.1&&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>";
}
?>
可以看到,相比Low级别的代码,服务器端对ip参数做了一定过滤,即把”&&” 、”;”删除,本质上采用的是黑名单机制,因此依旧存在安全问题。
所以即使过滤了&&,可以用&来替代:127.0.0.1 & net user;
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>";
}
?>
相比Medium级别的代码,High级别的代码进一步完善了黑名单,但黑名单看似过滤了所有的非法字符,其实仔细观察到是把|(注意这里|后有一个空格)替换为空字符,于是 |成了“漏网之鱼”。
|是管道符,表示将cmd1的输出作为cmd2的输入,并只打印cmd2执行的结果。
所以这里可以使用:127.0.0.1|dir;