新手教程-DVWA全級別教程之XSS

系統(tǒng)環(huán)境

因為網(wǎng)上關(guān)于dvwa的相關(guān)資料都比較舊,所以想重新過一邊dvwa的各個類型的漏洞,順帶初步入門php代碼審計相關(guān)的知識。環(huán)境安裝可以直接參照網(wǎng)上教程新手指南:手把手教你如何搭建自己的滲透測試環(huán)境,已經(jīng)寫的非常詳細,可以直接按照教程一步步安裝。

簡介

XSS,全稱Cross Site Scripting,即跨站腳本攻擊,某種意義上也是一種注入攻擊,是指攻擊者在頁面中注入惡意的腳本代碼,當受害者訪問該頁面時,惡意代碼會在其瀏覽器上執(zhí)行,需要強調(diào)的是,XSS不僅僅限于JavaScript,還包括flash等其它腳本語言。根據(jù)惡意代碼是否存儲在服務(wù)器中,XSS可以分為存儲型的XSS與反射型的XSS。
DOM型的XSS由于其特殊性,常常被分為第三種,這是一種基于DOM樹的XSS。例如服務(wù)器端經(jīng)常使用document.boby.innerHtml等函數(shù)動態(tài)生成html頁面,如果這些函數(shù)在引用某些變量時沒有進行過濾或檢查,就會產(chǎn)生DOM型的XSS。DOM型XSS可能是存儲型,也有可能是反射型。
(注:下面的實驗都是在Firefox瀏覽器下進行的,感謝火狐沒做XSS filter)

反射型XSS

下面將對四種級別的代碼進行分析
Low服務(wù)器核心代碼

<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Feedback for end user
    echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}

?> 

可以看到,代碼直接飲用了name參數(shù),并沒有任何的過濾和檢查,存在明顯的XSS漏洞。
漏洞利用
輸入<script>alert(/xss/)</script>,成功彈框:


image.png

Medium級別服務(wù)器核心代碼

<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?> 

可以看到,這里對輸入進行了過濾,基于黑名單的思想,使用str_replace函數(shù)將輸入中的<script>刪除,這種防護機制是可以被輕松繞過的。
漏洞利用
1.雙寫繞過
輸入<sc<script>ript>alert(/xss/)</script>,成功彈框:


image.png

2.大小寫混淆繞過
輸入<ScRipt>alert(/xss/)</script>,成功彈框:


image.png

High服務(wù)器端核心代碼

<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?> 

可以看到,High級別的代碼同樣使用黑名單過濾輸入,preg_replace() 函數(shù)用于正則表達式的搜索和替換,這使得雙寫繞過、大小寫混淆繞過(正則表達式中i表示不區(qū)分大小寫)不再有效。
漏洞利用
雖然無法使用<script>標簽注入XSS代碼,但是可以通過img、body等標簽的事件或者iframe等標簽的src注入惡意的js代碼。
輸入<img src=1 onerror=alert(/xss/)>,成功彈框:


image.png

Impossible服務(wù)端核心代碼

<?php

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

可以看到,Impossible級別的代碼使用htmlspecialchars函數(shù)把預(yù)定義的字符&、”、 ’、<、>轉(zhuǎn)換為 HTML 實體,防止瀏覽器將其作為HTML元素。

存儲型XSS

接下來對四種級別的代碼進行分析

Low級別服務(wù)器核心代碼

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = stripslashes( $message );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitize name input
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?> 

相關(guān)函數(shù)介紹
trim(string,charlist)
函數(shù)移除字符串兩側(cè)的空白字符或其他預(yù)定義字符,預(yù)定義字符包括、\t、\n、\x0B、\r以及空格,可選參數(shù)charlist支持添加額外需要刪除的字符。
mysql_real_escape_string(string,connection)
函數(shù)會對字符串中的特殊符號(\x00,\n,\r,\,‘,“,\x1a)進行轉(zhuǎn)義。
stripslashes(string)
函數(shù)刪除字符串中的反斜杠。
可以看到,對輸入并沒有做XSS方面的過濾與檢查,且存儲在數(shù)據(jù)庫中,因此這里存在明顯的存儲型XSS漏洞。
漏洞利用
message一欄輸入<script>alert(/xss/)</script>,成功彈框:


image.png

Medium服務(wù)器核心代碼

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = strip_tags( addslashes( $message ) );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = str_replace( '<script>', '', $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?> 

相關(guān)函數(shù)說明
strip_tags() 函數(shù)剝?nèi)プ址械?HTML、XML 以及 PHP 的標簽,但允許使用<b>標簽。
addslashes() 函數(shù)返回在預(yù)定義字符(單引號、雙引號、反斜杠、NULL)之前添加反斜杠的字符串。
可以看到,由于對message參數(shù)使用了htmlspecialchars函數(shù)進行編碼,因此無法再通過message參數(shù)注入XSS代碼,但是對于name參數(shù),只是簡單過濾了<script>字符串,仍然存在存儲型的XSS。
漏洞利用
1.雙寫繞過
抓包改name參數(shù)為<sc<script>ript>alert(/xss/)</script>:


image.png

2.大小寫混淆繞過
抓包改name參數(shù)為<Script>alert(/xss/)</script>:


image.png

High服務(wù)器核心代碼

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = strip_tags( addslashes( $message ) );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?> 

可以看到,這里使用正則表達式過濾了<script>標簽,但是卻忽略了img、iframe等其它危險的標簽,因此name參數(shù)依舊存在存儲型XSS。
漏洞利用
抓包改name參數(shù)為<img src=1 onerror=alert(1)>:


image.png

Impossible服務(wù)器端核心代碼

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = stripslashes( $message );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = stripslashes( $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $name = htmlspecialchars( $name );

    // Update database
    $data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
    $data->bindParam( ':message', $message, PDO::PARAM_STR );
    $data->bindParam( ':name', $name, PDO::PARAM_STR );
    $data->execute();
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

可以看到,通過使用htmlspecialchars函數(shù),解決了XSS,但是要注意的是,如果htmlspecialchars函數(shù)使用不當,攻擊者就可以通過編碼的方式繞過函數(shù)進行XSS注入,尤其是DOM型的XSS。

這一系列文章主要參考freebuf文檔,并自己手動實驗記錄完成,主要作為一種練習的記錄。方便自己查找

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容