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>
可以利用:
- 雙寫繞過
- 輸入
<sc<script>ript>alert(/xss/)</script>
,成功彈框
- 大小寫混淆繞過
- 輸入
<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)之前新增反斜槓的字串
做法:
- 雙寫繞過
抓包改name引數為<sc<script>ript>alert(/xss/)</script>
- 大小寫混淆繞過
抓包改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