【笔记】网易微专业-Web安全工程师-04.WEB安全实战-3.命令注入

命令注入(Command Injection):是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。

前面的基础课程中,我们提到命令注入需要三个条件:

1. 是否调用系统命令?

2. 函数/参数是否可控?

3. 是否拼接输入?

具体怎么应用,我们在接下去的实战中学习和体会。

DVWA实战:

1. 打开phpStudy或xampp,运行Apach和MySQL;

2. 浏览器进入DVWA主界面,在左侧栏选择DVWA Security安全等级为Low,然后进入Command Injection;

3. 我们输入一个IP提交后,发现返回了对这个IP进行Ping的结果。

注:如果返回乱码,可以试试如下方法:

找到DVWA目录下/dvwa/includes里的dvwaPage.inc.php文件,把字符集utf-8改为gb2312 ,保存一下便可。

// Send Headers + main HTML code
Header( 'Cache-Control: no-cache, must-revalidate');   // HTTP/1.1
//Header( 'Content-Type: text/html;charset=utf-8' );     // TODO- proper XHTML headers...
Header( 'Content-Type: text/html;charset=gb2312' );     // TODO- proper XHTML headers...
Header( 'Expires: Tue, 23 Jun 2009 12:00:00 GMT' );    // Date in the past

其实就跟我们自己进Windows的cmd里ping是一样的。因此,我们猜想后台肯定也是调用了系统的命令,并且将输入的参数进行拼接:

// 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 );
    }

因此,这边的提交操作满足了命令注入的三个条件,存在命令注入漏洞。

4. 如果我们输入123.125.114.144 && net user,那么会得到如下信息:

一个简单的命令注入漏洞就这样被利用了,只需要常见的命令连接符(&,&&,|,||,;等)和系统命令,如果输入的命令更具威胁性,那么这个危害就更大了,例如在Linux下输入127.0.0.1&&cat /etc/shadow甚至可以读取shadow文件。

5. 接下去我们把安全等级调到medium,发现报错了:错误的参数 net。我们来看看后台的代码,发现对”&&” 、”;”进行过滤,本质上是黑名单的方式。

// Set blacklist
$substitutions = array(
    '&&' => '',
    ';'  => '',
);

但是黑名单的过滤有限,我们可以利用&来攻击漏洞,输入123.125.114.144 & net user即可,另外,既然会把关键连接符过滤,何不反过来利用,构造&;&连接符,这样当;被过滤后,&&发挥了功效。

6. 接下去我们看看high等级的命令注入,发现上述方法也失效了,查看后台代码,发现对更多的命令连接符进行了过滤。

// Set blacklist
$substitutions = array(
    '&'  => '',
    ';'  => '',
    '| ' => '',
    '-'  => '',
    '$'  => '',
    '('  => '',
    ')'  => '',
    '`'  => '',
    '||' => '',
);

本质上仍然是黑名单的方式,所以仍然存在局限性。例如代码中的'| '后面有个空格,因此,我们直接输入123.125.114.144|net user即可。

另外,对于无回显的情况,可以使用延时命令查看响应速度(如Windows下的ping 127.0.0.1 -n 5 > nul或Linux下的sleep 5)或搭建服务器查看是否有接收到请求(Windows下的ping,telnet或者Linux下的wget,curl等)等方法;

7. 最后我们来看看impossible等级的命令注入,发现用上述的方法不可行,而且报错信息也更改了:ERROR: You have entered an invalid IP。查看后台代码,发现对参数ip进行了严格的限制,只有“数字.数字.数字.数字”的输入才会被接收执行,有效的修复了命令注入漏洞。

// 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];

实战心得:

使用白名单对用户输入的命令进行限制,尽量不要使用黑名单,最好是要遵守对一切输入不可信任的原则,对输入进行严格的校验。

原文地址:https://www.cnblogs.com/kplayer/p/8467607.html