1. 程式人生 > 實用技巧 >DVWA各等級XSS

DVWA各等級XSS

xss原理及基本介紹

  • XSS,全稱Cross Site Scripting,即跨站指令碼攻擊,某種意義上也是一種注入攻擊,是指攻擊者在頁面中注入惡意的指令碼程式碼,當受害者訪問該頁面時,惡意程式碼會在其瀏覽器上執行,需要強調的是,XSS不僅僅限於JavaScript,還包括flash等其它指令碼語言。根據惡意程式碼是否儲存在伺服器中,XSS可以分為儲存型的XSS與反射型的XSS。

  • DOM型的XSS由於其特殊性,常常被分為第三種,這是一種基於DOM樹的XSS。例如伺服器端經常使用document.boby.innerHtml等函式動態生成html頁面,如果這些函式在引用某些變數時沒有進行過濾或檢查,就會產生DOM型的XSS。DOM型XSS可能是儲存型,也有可能是反射型。

反射性xss

low

原始碼:

<?php 

// Is there any input? 

if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { 

    // Feedback for end user 

    echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>'; 

} 

?>

程式碼直接引用了name引數,並沒有任何的過濾與檢查,存在明顯的XSS漏洞

  • 輸入'<script> alert(/xss/) </script>'
    ,成功彈框

medium

原始碼:

<?php 
// 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函式將輸入中的<script>

刪除,這種防護機制是可以被輕鬆繞過
可以利用:

  1. 雙寫繞過
  • 輸入<sc<script>ript>alert(/xss/)</script>,成功彈框
  1. 大小寫混淆繞過
  • 輸入<ScRipt>alert(/xss/)</script>,成功彈框

high

原始碼:

<?php 
// 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() 函式用於正則表示式的搜尋和替換,這使得雙寫繞過、大小寫混淆繞過(正則表示式中i表示不區分大小寫)不再有效

  • 利用:
    輸入<img src=1 onerror=alert(/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(); 
?>

Impossible級別的程式碼使用htmlspecialchars函式把預定義的字元&、”、 ’、<、>轉換為 HTML 實體,防止瀏覽器將其作為HTML元素

儲存型xss

Low

原始碼:

<?php 
if( isset( $_POST[ 'btnSign' ] ) ) { 
    // Get input 
    $message = trim( $_POST[ 'mtxMessage' ] ); 
    $name    = trim( $_POST[ 'txtName' ] ); 
    // Sanitize message input 
    $message = stripslashes( $message ); 
    $message = mysql_real_escape_string( $message ); 
    // Sanitize name input 
    $name = mysql_real_escape_string( $name ); 
    // Update database 
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; 
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 
    //mysql_close(); 
} 
?>

需要學習的函式

trim(string,charlist)

函式移除字串兩側的空白字元或其他預定義字元,預定義字元包括、\t、\n、\x0B、\r以及空格,可選引數charlist支援新增額外需要刪除的字元。

mysql_real_escape_string(string,connection)

函式會對字串中的特殊符號(\x00,\n,\r,\,',",\x1a)進行轉義。

stripslashes(string)

函式刪除字串中的反斜槓

做法:

message一欄輸入<script>alert(/xss/)</script>,成功彈框

name一欄前端有字數限制,抓包改為<script>alert(/name/)</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 = mysql_real_escape_string( $message ); 
    $message = htmlspecialchars( $message ); 
    // Sanitize name input 
    $name = str_replace( '<script>', '', $name ); 
    $name = mysql_real_escape_string( $name ); 
    // Update database 
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; 
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 
    //mysql_close(); 
} 

需要學習的函式

strip_tags()

函式剝去字串中的 HTML、XML 以及 PHP 的標籤,但允許使用標籤。

addslashes()

函式返回在預定義字元(單引號、雙引號、反斜槓、NULL)之前新增反斜槓的字串

做法:

  1. 雙寫繞過

抓包改name引數為<sc<script>ript>alert(/xss/)</script>

  1. 大小寫混淆繞過

抓包改name引數為<Script>alert(/xss/)</script>

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 = mysql_real_escape_string( $message ); 
    $message = htmlspecialchars( $message ); 
    // Sanitize name input 
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); 
    $name = mysql_real_escape_string( $name ); 
    // Update database 
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; 
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 
    //mysql_close(); 
} 
?>

使用正則表示式過濾了<script>標籤,但是卻忽略了img、iframe等其它危險的標籤

因此name引數依舊存在儲存型XSS

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 = mysql_real_escape_string( $message ); 
    $message = htmlspecialchars( $message ); 
    // Sanitize name input 
    $name = stripslashes( $name ); 
    $name = mysql_real_escape_string( $name ); 
    $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函式,解決了XSS,但是要注意的是,如果htmlspecialchars函式使用不當,攻擊者就可以通過編碼的方式繞過函式進行XSS注入,尤其是DOM型的XSS

DOM型