DVWA簡介
DVWA(Damn Vulnerable Web Application)是一個用來進行安全脆弱性鑒定的PHP/MySQL Web應用,旨在為安全專業人員測試自己的專業技能和工具提供合法的環境,幫助web開發者更好的理解web應用安全防范的過程。
DVWA共有十個模塊,分別是Brute Force(暴力(破解))、Command Injection(命令行注入)、CSRF(跨站請求偽造)、File Inclusion(文件包含)、File Upload(文件上傳)、Insecure CAPTCHA(不安全的驗證碼)、SQL Injection(SQL注入)、SQL Injection(Blind)(SQL盲注)、XSS(Reflected)(反射型跨站腳本)、XSS(Stored)(存儲型跨站腳本)。
需要注意的是,DVWA 1.9的代碼分為四種安全級別:Low,Medium,High,Impossible。初學者可以通過比較四種級別的代碼,接觸到一些PHP代碼審計的內容。
Command Injection
Command Injection,即命令注入,是指通過提交惡意構造的參數破壞命令語句結構,從而達到執行惡意命令的目的。PHP命令注入攻擊漏洞是PHP應用程序中常見的腳本漏洞之一,國內著名的Web應用程序Discuz!、DedeCMS等都曾經存在過該類型漏洞。
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>"; } ?>
stristr(string,search,before_search)
stristr函數搜索字符串在另一字符串中的第一次出現,返回字符串的剩余部分(從匹配點),如果未找到所搜索的字符串,則返回FALSE。參數string規定被搜索的字符串,參數search規定要搜索的字符串(如果該參數是數字,則搜索匹配該數字對應的ASCII值的字符),可選參數before_true為布爾型,默認為“false”,如果設置為“true”,函數將返回search參數第一次出現之前的字符串部分。
php_uname(mode)
這個函數會返回運行php的操作系統的相關描述,參數mode可取值”a” (此為默認,包含序列”s n r v m”里的所有模式),”s”(返回操作系統名稱),”n”(返回主機名),” r”(返回版本名稱),”v”(返回版本信息), ”m”(返回機器類型)。
可以看到,服務器通過判斷操作系統執行不同ping命令,但是對ip參數並未做任何的過濾,導致了嚴重的命令注入漏洞。
前置知識:
Command 1&&Command 2
先執行Command 1,執行成功后執行Command 2,否則不執行Command 2
Command 1&Command 2
先執行Command 1,不管是否成功,都會執行Command
Command 1|Command 2
“|”是管道符,表示將Command 1的輸出作為Command 2的輸入,並且只打印Command 2執行的結果。
所以我們可以:ping 192.168.5.100(主機地址)&&net user
或者其他的命令,比如創建用戶,從而達到我們滲透的目的。
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>"; } ?>
可以看到,相比Low級別的代碼,服務器端對ip參數做了一定過濾,即把”&&” 、”;”刪除,本質上采用的是黑名單機制,因此依舊存在安全問題。
因為北過濾的只有‘&&’和‘;’,所以“&”不會有影響
輸入192.168.5.100&net user
法二:使用的轉義函數把“&&”“、”“;”替換為空字符,因此可以采用以下方式繞過:
192.168.5.100&;&net user 這樣;被轉義成空,就能順利執行兩個命令
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>"; } ?>
代碼進一步完善了過濾名單,但是仔細觀察‘| ’替換為空格,后面還有一個空格,所以‘|’就可以利用。
192.168.5.100|net user