DVWA 實驗報告:2、命令注入

文章更新於:2020-04-11
注:如何搭建環境參見:搭建DVWA Web滲透測試靶場

一、介紹

1.1、官方說明

The purpose of the command injection attack is to inject and execute commands specified by the attacker in the vulnerable application. In situation like this, the application, which executes unwanted system commands, is like a pseudo system shell, and the attacker may use it as any authorized system user. However, commands are executed with the same privileges and environment as the web service has.

Command injection attacks are possible in most cases because of lack of correct input data validation, which can be manipulated by the attacker (forms, cookies, HTTP headers etc.).

The syntax and commands may differ between the Operating Systems (OS), such as Linux and Windows, depending on their desired actions.

This attack may also be called “Remote Command Execution (RCE)”.

1.2、總結

總的來說就是如果Web服務器沒有配置妥當,則可能產生命令注入漏洞。究其原因,是沒有進行充分的驗證訪問者身份。

不同的操作系統比如(Linux 和 Windows)的命令格式是不相同的。

這種攻擊方式也稱爲 遠程命令執行 (RCE)

二、命令注入實踐

2.1、安全級別:LOW

>> 查看源碼

  1. 此對話框原意是輸入一個 IP 或域名進行 PING 測試。

題目界面

  1. 輸入IP測試

pingIP

  1. 點擊頁面右下角 View Source 得到如下源碼:
<?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 命令,然後將結果原樣返回到前端。

這是非常危險的,如果可以使用 &&&|; 等命令分隔符同事執行多條命令。則可任意執行命令,是有可能可以在系統上創建用戶留下後門的。
比如我們執行 | net user add hello 1234

如果系統有安全軟件,可能會有如下提示:

安全防護

如果沒有安全軟件,命令執行成功將有可能在系統留下後門。

>>嘗試注入

注1:常用 &|;作爲命令分隔符。
注2:鍵盤左上角的反引號 ` ,會忽略掉外部的雙引號先執行。

  1. 嘗試用分號 ;分隔命令進行注入
    注:這裏使用的是 Linux 環境下的 IP查看命令。

嘗試注入

  1. 嘗試獲取主機密碼文件內容

獲取密碼文件

  1. 嘗試用豎線 | 分隔命令進行注入
    注:這裏使用的是 Windows 環境下的 IP查看命令。

命令注入

  1. 嘗試使用與符號 & 分割命令進行注入

命令注入

2.2、安全級別: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>";
}

?> 

上述代碼可以看出,程序對 &&; 進行了替換成空字符串,但其他符號沒有處理,所以其他分隔符依然有效。

>>嘗試注入

  1. 嘗試使用 | tree 命令

嘗試注入

  1. 嘗試創建文件 `| echo “hello” > hello.txt" | dir

創建文件

2.3、安全級別: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>";
}

?>

這裏可以看到程序對 &;|-$()、`、|| 進行了替換成空字符串,但同時可以注意到,|後面有一個空格。

>>嘗試注入

  1. 嘗試使用 | tree 進行注入

嘗試注入

  1. 嘗試使用 || tree

注入失敗

2.4、安全級別: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();

?> 

上述代碼可以看出,程序先對輸入進行了點.分割成幾部分,然後分別判斷前四部分是否數字和是否總共四部分,如果是再進行拼接。那…這還命令注入個錘子!!

>> 可以嘗試注入,但沒必要

  1. 在上述幾個代碼的變化中,我們可以看到,如果沒有任何過濾,那服務器將是十分不安全的。

  2. 即便使用了一些黑名單過濾手段,但你卻無法保證你完全過濾掉了一些有害的信息。

  3. 所以比較穩妥的方法,還是使用白名單過濾手段,讓經過嚴格過濾的數據通過,其他的一律拒絕。這樣避免了一些未知的風險。

2.5、知識拓展

命令分隔符 說明
; 分號在linux命令執行的時候,可以分隔多條命令
& Windows順序執行,Linux先執行後面的命令
&& 與,前面的命令執行成功後纔可以執行下面的命令
| 管道符,前面的命令輸出結果爲後面的命令輸入的內容
|| 或,前面的命令執行失敗後纔會執行後面的命令

三、Enjoy!

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