【DVWA】Command Injection

【DVWA】Command Injection


Command Injection即命令注入,应用程序有时调用一些执行系统命令的函数,如在PHP中,使用system、exec、shell_exec、passthru、popen、proc_popen等函数可以执行系统命令。当黑客能控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令注入漏洞。


一、low级别

1、漏洞测试

image-20210304085027729

如图所示,ipconfig执行成功,当然在Linux下也可以通过cat查看一些敏感文件,如/etc/password或者shadow文件。文件详解

关于符号的使用:

windows与Linux

“|”:command1 | command2; 直接执行后面的命令;

“||”:command1 || command2; 只有前面为假(执行错误)才会执行后面的命令。ping 2 || ipcongfig

“&”:command1 & command2; 无论前面真假,都会执行后面的语句。

“&&”:command1 && command2; 只有前面为真,才会执行后面的语句。Ping 127.0.0.1 && whoami

另Linux中

“;”:command1 ; command2; 执行完前面的语句再执行后面的语句。

2、源码分析

<?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>";
}

?> 

函数详解:

php_uname('mode'):其中mode为单个字符

  • 'a':此为默认。包含序列 "s n r v m" 里的所有模式。
  • 's':操作系统名称。例如: FreeBSD
  • 'n':主机名。例如: localhost.example.com
  • 'r':版本名称,例如: 5.1.2-RELEASE
  • 'v':版本信息。操作系统之间有很大的不同。
  • 'm':机器类型。例如:i386

shell_exec('cmd'):其中cmd为要执行的系统命令

stristr()函数:搜索字符串在另一个字符串中的第一次出现,并返回该字符串以及剩余部分是二进制安全的,不区分大小写。如需区分大小写则应使用strstr()函数

2、medium级别

1、漏洞测试

输入222.24.28.118 && hostname 出错:

image-20210304093829955

输入 8 | hostname 成功执行:

image-20210304093705311

2、源码分析

<?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>";
}

?> 

如上面源代码,采用的是黑名单过滤机制,将用户传入的参数中的&& 和 ;替换为空从而试图防御命令注入,但可以使用其他符号,如|, ||, &。

也可以使用拼凑法222.24.28.118 &;& ipconfig

image-20210304094805110

三、high级别


1、漏洞测试

输入222.24.28.118 || ipconfig 成功执行:

image-20210304094153721

输入222.24.28.118 |whoami成功执行:

image-20210304140441984

2、源码分析

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    
    
    // Get input
    $target = trim($_REQUEST[ 'ip' ]);  //trim函数去除开头和结尾的空格,以及换行符\n,Tab键\t等

    // 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级别完善了黑名单机制,但是仔细看发现它过滤的是|加空格,所以直接打|就可绕过。

而且222.24.28.118 || ipconfig也可绕过,原因是过滤机制是按照数组中的顺序过滤的,先过滤|空格,然后剩下222.24.28.118 |ipconfig也可执行成功。


四、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 );  //把字符串打散为数组,这里是把ip用点区分为四个数组元素

    // Check IF each octet is an integer  //检查每个元素是否是一个数字,并且该数组有4个元素
    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];
          //将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>";
    }
    else {
    
    
        // Ops. Let the user name theres a mistake
        echo '<pre>ERROR: You have entered an invalid IP.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

从上述代码可以看出,他是先将传入的字符串以‘.’为分隔,打散成一个数组,并且判断该数组中每个元素是否为数字,该数组是否一共有4个元素。比较严格的做了格式限制,绕过比较困难。


五、漏洞修复建议


1、不使用

尽量不要使用命令执行函数。

对于php语言来讲,不能完全控制的危险函数最好不要使用。

2、若非要使用,在参数传入前一定做过滤。

客户端提交的变量在进入执行命令函数前要做好过滤和检测。

在使用动态函数之前,确保使用的函数是指定的函数之一。

猜你喜欢

转载自blog.csdn.net/qq_43665434/article/details/114367996
今日推荐