-
前言
上一篇文章中,对命令注入进行了简单的分析,有兴趣的可以去看一看,文章地址 https://www.cnblogs.com/lxfweb/p/12828754.html,今天这篇文章以DVWA的Command Injection(命令注入)模块为例进行演示与分析,本地搭建DVWA程序可以看这篇文章 https://www.cnblogs.com/lxfweb/p/12678463.html,通过对DVWA不同等级的代码分析,看看它是如何做的防御。
漏洞利用与分析
low级别(低级别)
首先查看low级别的核心代码
<?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(),php_uname(),函数,这是用来判断当前的系统是否是Windows,因为Windows和Linux下的ping命令执行参数是不同的。接下来是用shell_exec函数来执行ping命令,并将结果输出。我们发现low级别的代码,对用户的输入没有做任何的过滤。存在很大的安全隐患。例如使用管道符“|”查看当前端口,输入下列内容
127.0.0.1|netstat -ano
结果如下图
这里不止可以使用“|”,在DOS下允许同时执行多条命令的符号主要有以下几个
- & 连接符 执行完第一个命令,执行第二个命令
- && 只有上一个执行成功,才执行下一个命令
- | 管道符 让前一命令的输出当做后一命令的输入,就是说前面命令的结果当做一个参数传递给后面命令处理
- || 只有上一个执行失败,才执行下一个命令
可以用连接符直接接net user zhangsan 123/add 创建用户 接着连接提权命令 net localgroup administrators zhangsan /add 拿下整个服务器
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>";
}
?>
我们发现,中级的代码,对参数做了一点过滤,把&&和;删除,相当于黑名单的形式,在Linux中;也可以起连接作用,依次执行多个命令。我们可以尝试| || & &;& ,这里以||举例,||前面报错,后面执行咱们构造的命令,结果如下图
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(无漏洞)
查看核心代码
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();
?>
通过查看Impossible级别的代码加入了Anti-CSRF token,并且采用白名单的方式,对参数ip进行了严格的限制,只接受X.X.X.X(X只能为数字),因此不存在命令执行漏洞。
来源:oschina
链接:https://my.oschina.net/u/4393390/blog/4268192