網絡安全入門之命令行注入 DVWA Command Injection Low to High Level

1. 背景

最近需要補充一下網絡安全方面的知識,於是就從基礎的靶場 DVWA (Damn Vulnerable Web Application) 開始刷起,這一篇是關於從LowHigh難度的命令行注入的內容。

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

公衆號複雜網絡與機器學習

歡迎關注/轉載,有問題歡迎通過郵箱交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章