DVWA系列之XSS

前期準備:linux下搭建dvwa需要lamp環境,其php版本不能太高,php7.0無法使用,php5.6可以;

XSS定義

CSS(Cross Site Script)又叫XSS,中文意思:跨站腳本攻擊。它指的是惡意攻擊者往Web頁面裏插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web裏面的html代碼會被執行。XSS的攻擊目標是爲了盜取客戶端的cookie或者其他網站用於識別客戶端身份的敏感信息。獲取到合法用戶的信息後,攻擊者甚至可以假冒最終用戶與網站進行交互。

XSS的原理

也就是往HTML中注入腳本,HTML指定了腳本標記<script></script>.在沒有過濾字符的情況下,只需要保持完整無錯的腳本標記即可觸發XSS,假如我們在某個資料表單提交內容,表單提交內容就是某個標記屬性所賦的值,我們可以構造如下值來閉和標記來構造完整無錯的腳本標記,"><script>alert('Xss');</script><"

反射型XSS

等級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>';
}

?> 

這裏隨便輸入Word試一下:
word<script>alert('Xss');</script> ;

基本的xss

觀察到調用函數輸出了Xss彈窗,後面爲Word,其實<script>”注入語句“</script>可以完成許多功能。

等級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>";
}

?> 

觀察發現使用str_replace進行了黑名單過濾,繞過這個不成問題,使用

雙寫繞過

<scri<script>pt>alert(/test/);</script>

大小寫混寫繞過

<sCripT>alert(/test/);</script>

xss

等級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>";
}

?> 

使用正則進行匹配,過濾了大小寫混合寫入已經雙寫,但是可以使用img、body等標籤的事件以及iframe標籤的src注入惡意的js代碼進行漏洞利用
<img src=1 onerror=alert('test')>

xss

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

htmlspecialchars() 函數把一些預定義的字符轉換爲 HTML 實體。以防止瀏覽器將其作爲HTML元素。這樣會將用戶輸入的內容都不作爲標籤以提高安全性。
預定義的字符是:

& (和號)成爲 &amp;
" (雙引號)成爲 &quot;
' (單引號)成爲 '
< (小於)成爲 &lt;
> (大於)成爲 &gt;

一些常用的xss語句

   <script>alert(/test/)</script> 最普通的xss代碼
   <script>alert(document.cookie);</script> 獲取cookie
   <img src="javascript:alert(/test/)"> img鏈接地址xss
   <script src="test.js"> <script> 外部調用攻擊代碼ls.js
   <script alert('test)</SCRIPT> 註釋方法防止過濾
   <img src="" onerror=alert("xss")> 加載圖像失敗執行
   <iframe onload=alert('test')> 框架
   <script>location='test.com';</script> 跳轉某頁面

存儲型XSS

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

?> 
部分函數講解

trim() 函數移除字符串兩側的空白字符或其他預定義字符。
相關函數:

ltrim() - 移除字符串左側的空白字符或其他預定義字符
rtrim() - 移除字符串右側的空白字符或其他預定義字符

stripslashes():刪除由 addslashes() 函數添加的反斜槓。該函數用於清理從數據庫或 HTML 表單中取回的數據。(若是連續二個反斜槓,則去掉一個,保留一個;若只有一個反斜槓,就直接去掉。);
mysqli_real_escape_string:轉義字符串中的特殊字符;

name欄輸入發現有字數限制,那就抓包改數據;

抓包

message欄正常輸入即可,<script>alert('test');</script>

等級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)之前添加反斜槓的字符串。
其對message參數使用了htmlspecialchars函數進行編碼,因此無法對message參數注入XSS代碼,但是對於name參數,簡單過濾了<script>字符串,仍然存在存儲型的XSS。
使用雙寫<scri<script>pt>alert('test')

改包

成功彈框
medium

大小寫混合繞過<sCrIpt>alert('test')

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

這裏使用正則表達式過濾了<script>標籤,但是依然存在img、iframe等其它危險的標籤,因此name參數仍然有存儲型XSS
抓包改name數據=<img src=1 onerror=alert('test')>

bao.png

成功彈框
圖片.png

等級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();

?> 

這個就比較高級了,對name和message均進行了htmlspecialchars過濾

存儲型和反射型的區別
  • 存儲型
    存儲型XSS,持久型,代碼是存儲在服務器中的,如果沒有過濾或過濾不嚴,那麼這些代碼將儲存到服務器中,用戶訪問該頁面的時候觸發代碼執行。這種XSS比較危險,容易造成蠕蟲,盜竊cookie等。
  • 反射型
    反射型XSS,非持久化,需要欺騙用戶手動去點擊鏈接才能觸發XSS代碼,一般容易出現在搜索頁面。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章