DVWA-1.9系列一共分爲10個功能模塊:
- Brute Force(暴力破解)
- Command Injection(命令行注入)
- CSRF(跨站請求僞造)
- File Inclusion(文件包含)
- File Upload(文件上傳)
- Insecure CAPTCHA(不安全的驗證碼)
- SQL Injection(SQL注入)
- SQL Injection(Blind)(SQL盲注)
- XSS(Reflected)(反射型跨站腳本)
- XSS(Stored)(存儲型跨站腳本)
之前兩篇文章分別是介紹了DVWA以及第一個功能模塊Brute Force(暴力破解)。
這一篇我們繼續介紹第二個功能模塊:Command Injection(命令行注入)
1. Command Injection簡介
Command Injection(命令注入),是指通過提交惡意構造的參數破壞命令語句結構,從而達到執行惡意命令的目的。PHP命令注入攻擊漏洞是PHP應用程序中常見的腳本漏洞之一。
該模塊主要實現的是一個ping 某個ip的功能,但由於對輸入的內容驗證不完善導致命令執行漏洞。
主要頁面如下:
2. Low 安全級別分析
首先我們把安全級別設置爲Low級別。查看源代碼:
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命令,但是對ip參數並未做任何的過濾,導致了嚴重的命令注入漏洞。
- stristr() 函數搜索字符串在另一字符串中的第一次出現。
- 註釋:該函數是二進制安全的。
- 註釋:該函數是不區分大小寫的。如需進行區分大小寫的搜索,請使用 strstr() 函數。
- 語法:stristr(string,search,before_search)
這個函數會返回運行php的操作系統的相關描述,參數mode可取值:
- ”a”(此爲默認,包含序列”s n r v m”裏的所有模式),
- ”s”(返回操作系統名稱),
- ”n”(返回主機名),
- “r”(返回版本名稱),
- ”v”(返回版本信息),
- ”m”(返回機器類型)。
漏洞利用:
無論是linux系統還是windows系統,我們都可以用&&來執行多條命令語句。所以我們執行的payload可以是127.0.0.1&&whoami
可以發現返回了執行結果,顯示了linux的用戶名:
3. Medium 安全級別分析
首先我們把安全級別設置爲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>";
}
?>
通過源代碼我們可以看到,代碼中的主要過濾原則是採用黑名單的方式:
$substitutions = array(
'&&' => '',
';' => '',
);
把”&&”和”;”直接刪除,但是隻是單純了刪除了這兩個,還是存在命令執行漏洞。
漏洞利用:
通過源碼我們可以知道,他主要就是把”&&”和”;”放進了黑名單裏,不可以用“&&”了,但是“&”任然可以使用呀。這裏我們需要說一下“&&”,“;”和“&”的區別:
- command1&command2&command3 三個命令同時執行
- command1;command2;command3 不管前面命令執行成功沒有,後面的命令繼續執行
- command1&&command2 只有前面命令執行成功,後面命令才繼續執行
所以我們使用payload127.0.0.1&whoami
查看返回結果:
成功顯示用戶。
4. High 安全級別分析
把安全級別設置爲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級別把黑名單機制更加擴大了。我們可以看到代碼中把'| '
替換成了空白符,我們可以延伸一下'|'
卻沒有被過濾掉。
嘗試使用payload127.0.0.1|whoami
查看返回結果:
成功顯示用戶。
- Command 1 | Command 2 “|”是管道符,表示將Command 1的輸出作爲Command 2的輸入,並且只打印Command 2執行的結果。
5. Impossible 安全級別分析
把安全級別設置爲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();
?>
通過源代碼分析我們可以看到:
該模塊中加入了Anti-CSRF token來防範CSRF攻擊,同時每次隨機生成了一個token,當用戶提交的時候,在服務器端比對一下token值是否正確,不正確就丟棄掉,正確就驗證通過。
// Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
通過加入stripslashes函數來對輸入的ip信息進行刪除字符串中的反斜槓操作。
$target = stripslashes( $target );
對輸入的信息通過“.”號進行分割,分割成多個數組。
// Split the IP into 4 octects $octet = explode( ".", $target );
然後採用白名單機制來驗證輸入的信息是不是都是數字組成,然後把所有的數字通過“.”進行拼接,這樣就保證了輸入的信息只能是以
數字.數字.數字.數字
的形式,避免了命令執行漏洞。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];