DVWA之Command Injection

2018-01-19  本文已影响0人  网络安全自修室

Command Injection(命令注入),是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一

DVWA-1.9系列一共分为10个功能模块:
dvwa
Brute Force(暴力破解)
Command Injection(命令行注入)
CSRF(跨站请求伪造)
File Inclusion(文件包含)
File Upload(文件上传)
Insecure CAPTCHA(不安全的验证码)
SQL Injection(SQL注入)
SQL Injection(Blind)(SQL盲注)
XSS(Reflected)(反射型跨站脚本)
XSS(Stored)(存储型跨站脚本)

好久没刷web了,先从Command Injection开刀吧

该模块主要实现的是一个ping 某个ip的功能,但由于对输入的内容验证不完善导致命令执行漏洞
图像 3.png
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>";
}

?> 

我们可以看到,服务器通过判断操作系统执行不同ping命令,但是对ip参数并未做任何的过滤,导致了严重的命令注入漏洞。

stristr()函数定义和用法:

php_uname(mode)函数定义和用法:

这个函数会返回运行php的操作系统的相关描述,参数mode可取值:

漏洞利用:

无论是linux系统还是windows系统,我们都可以用&&来执行多条命令语句。所以我们执行的payload可以是 127.0.0.1&&whoami可以发现返回了执行结果,故可以执行任意命令了哦
刚开始我还试了;号,没有执行和老版本的有点不同。

图像 4.png
Medium级源代码如下

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级别的payload就不能用了,但是该级别的缺点是只过滤了上述两种字符,这里我们还可以用&号、管道符| ||等直接绕过。

区别:

command1&command2&command3 三个命令同时执行
command1;command2;command3 不管前面命令执行成功没有,后面的命令继续执行
command1&&command2 只有前面命令执行成功,后面命令才继续执行
command1|command2 管道符的限制是只显示后面那条命令的执行结果
command1||command2是前面的命令执行失败,后面命令才继续执行和&&号的相反
成功执行
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>";
}

?> 

通过源代码可以看出,high级别把黑名单机制更加扩大了。我们可以看到代码中把'| '替换成了空白符,'|'却没有被过滤掉,可以构造payload 127.0.0.1|whoami

成功执行
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();

?> 

通过源代码分析我们可以看到:

该模块中加入了Anti-CSRF token来防范CSRF攻击,同时每次随机生成了一个token,当用户提交的时候,在服务器端比对一下token值是否正确,不正确就丢弃掉,正确就验证通过。

 // Check Anti-CSRF token 
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 

通过加入stripslashes函数来对输入的ip信息进行删除字符串中的反斜杠操作。

$target = stripslashes( $target ); 

对输入的信息通过“.”号进行分割,分割成多个数组。

 // Split the IP into 4 octects 
$octet = explode( ".", $target );

然后采用白名单机制来验证输入的信息是不是都是数字组成,然后把所有的数字通过“.”进行拼接,这样就保证了输入的信息只能是以数字.数字.数字.数字的形式,避免了命令执行漏洞。

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

所以几乎不可能单纯的命令执行,写站可以借鉴下~~~~

上一篇 下一篇

猜你喜欢

热点阅读