[网络安全] DVWA之 Command Injection 攻击姿势及解题详析合集

发布时间 2023-06-17 14:23:12作者: 秋说

Command Injection

命令注入(Command Injection)是一种安全漏洞,发生在应用程序使用用户提供的输入作为系统命令的一部分而未经充分验证和过滤的情况下。

当应用程序在构造系统命令时,如果没有对用户输入进行适当的验证和过滤,攻击者可以通过在用户输入中插入恶意命令来执行任意系统命令。这可能导致攻击者在系统上执行未经授权的操作,如执行恶意代码、访问敏感数据、修改系统配置等。

以下为在命令行中常见的操作符,用于控制命令的执行顺序和逻辑。

  1. ;:分号操作符用于在一行命令中按顺序执行多个命令。不论前一个命令是否执行成功,都会继续执行后面的命令。
    A;B //A不论正确与否都会执行B

  2. &:在命令后添加&,可以将命令放在后台执行,同时继续执行后面的命令。
    A&B //A后台运行,A和B同时执行

  3. &&:与操作符表示只有前一个命令执行成功(返回0),才会执行后面的命令。如果前一个命令执行失败(返回非零值),后面的命令将不会执行。
    A&&B //A执行成功后才会执行B

  4. |:管道操作符将前一个命令的输出结果作为后一个命令的输入参数。前一个命令的执行结果会被传递给后一个命令进行处理。
    A|B //A执行的输出结果作为B命令的参数,A不论正确与否,都会执行B

  5. ||:或操作符表示只有前一个命令执行失败(返回非零值),才会执行后面的命令。如果前一个命令执行成功(返回0),后面的命令将不会执行。
    A||B //A执行失败后才会执行B命令

Low level

源代码

<?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脚本,用于执行ping命令并将结果返回给用户。

在代码中,首先通过$_POST['Submit']检查是否收到了名为Submit的表单提交按钮的请求。如果得到了该请求,则会继续执行后续代码。

然后,从$_REQUEST['ip']获取名为ip的输入字段的值,该字段应该是一个IP地址或域名,表示要执行ping命令的目标。

接下来,使用php_uname('s')函数判断操作系统类型,如果包含字符串'Windows NT',则表示是Windows系统;否则,表示是*nix系统。

如果是Windows系统,则使用shell_exec()函数执行ping命令,并将结果赋给变量$cmd。如果是*nix系统,则执行带有'-c 4'参数的ping命令(表示发送4个ICMP回显请求),同样将结果赋给变量cmd。

最后,使用echo语句将结果以<pre>标签的形式输出给用户,保持格式化后的原样显示。

姿势

由于程序没有对输入参数进行过滤,用户端可以直接拼接特定的命令,来执行并获取想要的信息。

Payload:127.0.0.1&&ipconfig

127.0.0.1是一个特殊的IP地址,代表本地主机或本机回环地址。在命令中使用127.0.0.1时,实际上是在尝试与本地计算机进行通信。

而ipconfig是Windows操作系统上的命令,用于显示当前网络配置信息,包括IP地址、子网掩码、默认网关等。

因此,127.0.0.1 && ipconfig 的含义是先尝试与本地计算机进行通信,然后执行 ipconfig 命令来显示网络配置信息。

回显如下:

在这里插入图片描述
成功实现命令注入。

Medium level

源代码

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

代码审计

Medium等级对于用户输入的 IP 地址,使用了一些 黑名单 进行替换,以防止命令注入漏洞。

代码逻辑如下:

  1. 检查是否有名为 "Submit" 的表单提交按钮被点击。
  2. 获取用户输入的 IP 地址,存储在 $target 变量中。
  3. 设置一个黑名单数组 $substitutions,包含需要替换的替代字符,如 '&&' => ''';' => ''
  4. 使用 str_replace() 函数,将黑名单数组中的字符替换为空字符串,去除可能的命令注入字符。
  5. 通过判断操作系统类型来确定执行的 ping 命令。如果是 Windows 系统,则使用 shell_exec() 函数执行 ping 命令,否则使用 shell_exec() 执行带有 -c 4 参数的 ping 命令。
  6. 将命令执行的结果存储在 $cmd 变量中。
  7. 使用 <pre> 标签将结果格式化输出给用户。

姿势

由于黑名单只过滤了 &&;

故可使用以下操作符进行命令注入

127.0.0.1 & ipconfig

127.0.0.1 | ipconfig

111 || ipconfig    注意该操作符的执行条件:111执行失败才会执行ipconfig

回显如下:

在这里插入图片描述

High level

源代码

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = trim($_REQUEST[ 'ip' ]);

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

    // Remove any of the characters 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>";
}

?> 

代码审计

与之前的代码相比,这段代码对用户输入进行了更严格的过滤。

代码逻辑如下:

  1. 检查是否有名为 "Submit" 的表单提交按钮被点击。
  2. 获取用户输入的 IP 地址,并使用 trim() 函数去除首尾的空格,存储在 $target 变量中。
  3. 设置一个黑名单数组 $substitutions,目的是去除用户输入中的特殊字符。
  • & 替换为空字符串:这是为了防止使用逻辑 AND 运算符 && 进行命令注入。
  • ; 替换为空字符串:这是为了防止使用命令分隔符 ; 进行命令注入。
  • | 替换为空字符串:这是为了防止使用管道操作符 | 进行命令注入。
  • - 替换为空字符串:这是为了防止使用连字符 - 进行命令注入。
  • $ 替换为空字符串:这是为了防止直接使用美元符号 $ 进行命令注入。
  • (替换为空字符串:这是为了防止使用左括号 ( 进行命令注入。
  • ) 替换为空字符串:这是为了防止使用右括号 ) 进行命令注入。
  • ` 替换为空字符串:这是为了防止使用反引号进行命令注入。
  • || 替换为空字符串:这是为了防止使用逻辑 OR 运算符 || 进行命令注入。
  1. 使用 str_replace() 函数,将黑名单数组中的字符替换为空字符串,以防止任何特殊字符的注入。
  2. 通过判断操作系统类型来确定执行的 ping 命令。如果是 Windows 系统,则使用 shell_exec() 函数执行 ping 命令,否则使用 shell_exec() 执行带有 -c 4 参数的 ping 命令。
  3. 将命令执行的结果存储在 $cmd 变量中。
  4. 使用 <pre> 标签将结果格式化输出给用户。

姿势

  '| ' => ''

明显的是,黑名单只过滤了|及后面的空格,故仅使用|就可绕过:

在这里插入图片描述

Impossible level

源代码

<?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();

?> 

代码审计

代码流程如下:

  1. 检查是否有名为 "Submit" 的表单提交按钮被点击。
  2. 通过 checkToken() 函数检查反跨站请求伪造 (CSRF) 令牌的有效性,以确保请求的来源是合法的。
  3. 获取用户输入的 IP 地址,并使用 stripslashes() 函数去除可能的反斜杠转义。
  4. 使用 explode() 函数将 IP 地址按照 "." 分割成 4 个字段,并将字段存储在 $octet 数组中。
  5. 检查每个字段是否都是数字,并且 IP 地址是否包含 4 个字段。
  6. 如果上述条件均满足,将 IP 地址重新组合,并存储在 $target 变量中。
  7. 通过判断操作系统类型来确定执行的 ping 命令。如果是 Windows 系统,则使用 shell_exec() 函数执行 ping 命令,否则使用带有 -c 4 参数的 ping 命令。
  8. 将命令执行的结果存储在 $cmd 变量中。
  9. 使用 <pre> 标签将结果格式化输出给用户。

此外,代码还包括了以下功能:

  • generateSessionToken() 函数用于生成反 CSRF 令牌,以增加应用程序的安全性。
  • 如果输入的 IP 地址不合法(不是 4 个数字字段),则输出错误提示给用户。

总结

以上为 [网络安全] DVWA之 Command Injection 攻击姿势及解题详析合集,考察命令注入命令操作符PHP代码审计等知识点。

我是秋说,我们下次见。