命令执行漏洞是指攻击者可以随意执行系统命令,属于高危漏洞之一,也属于代码执行的范畴。不仅存在一B/S架构中,也存在于C/S架构中。
OS命令执行漏洞:在windows和linux系统下,"&&"的作用是将两条命令连起来执行,此外,&、||、|符号同样也可以作为命令连接符使用,如net user ||set、net user | set、net user & set,如果web应用没有过滤好输入,就变得相当危险,权限足够大的情况下,服务器可被攻击者直接攻陷。
命令执行漏洞 | 直接调用操作系统命令 |
---|---|
代码执行漏洞 | 靠执行脚本代码调用操作系统命令如eval(system(‘set’)) |
php命令执行:
部分函数用来执行外部应用程序:
system ( string $command ) | 执行外部程序,并且显示输出,如果 PHP 运行在服务器模块中, system() 函数还会尝试在每行输出完毕之后, 自动刷新 web 服务器的输出缓存。 |
---|---|
shell_exec() | 用于通过shell执行命令并以字符串的形式返回完整的输出。shell_exec是backtick操作符的别名,用于*nix。如果命令失败,则返回NULL,并且这些值对于错误检查不可靠。 |
exec() | 如果提供了 output 参数, 那么会用命令执行的输出填充此数组, 每行输出填充数组中的一个元素。 数组中的数据不包含行尾的空白字符,例如 \n 字符。 请注意,如果数组中已经包含了部分元素,exec() 函数会在数组末尾追加内容。如果你不想在数组末尾进行追加, 请在传入 exec() 函数之前 对数组使用 unset() 函数进行重置。 |
– | – |
passthru() | 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system() 函数。 常用来执行诸如 pbmplus 之类的可以直接输出图像流的命令。 通过设置 Content-type 为 image/gif, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP 脚本中直接输出图像到浏览器。 |
Low
解决乱码问题的方法:在DVWA-master\dvwa\includes目录下找到dvwaPage.inc.php文件中所有的”charset=utf-8”,修改”charset=gb2312”
1、查看服务器端源代码
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// 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>";
}
?>
函数解释:
stristr() | 搜索字符串在另一字符串中的第一次出现的位置 |
---|---|
$_REQUEST() | 获取以POST方法和GET方法提交的数据 |
2、查看客户端源代码
<div class="body_padded">
<h1>Vulnerability: Command Injection</h1>
<div class="vulnerable_code_area">
<h2>Ping a device</h2>
<form name="ping" action="#" method="post">
<p>
Enter an IP address:
<input type="text" name="ip" size="30">
<input type="submit" name="Submit" value="Submit">
</p>
</form>
<pre>
3、构造执行语句
在包含注入命令数据提交后可根据回显结果是否包含执行命令结果特征进行判断是否存在注入命令漏洞,例如在输入命令中包含 id 的数据,查看响应结果是否包含 uid 和gid。
分别填写以下提交数据:
127.0.0.1&&id:uid,gid
127.0.0.1&&net user:得到系统中所有用户
testcmdinjection||id
testcmdinjection||net user
127.0.0.1&id
127.0.0.1|net user
testcmdinjection&id
testcmdinjection|net user
也可自编python脚本进行命令注入。
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>";
}
?>
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>";
}
?>
针对输入数据删除&、;、-、$、(、)、`、||、|空格等字符(注意删除|空格,对|并不进行处理)
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();
?>
CSRF是跨站域请求伪造,加入Anti-CSRFtoken,服务器端对token进行验证,防止黑客利用保存用户验证信息的cookie来伪造请求。
输入数据会根据小数点进行拆分,拆分成四段再组合起来,恶意命令难以入侵。
修复建议
a) 使用白名单对提交数据类型和格式进行严格验证
b) 限制执行命令由用户提交,使用白名单限制执行命令
c) 避免 web 服务器启动用户权限过高