DVWA入门靶场实战(三)

接着上一篇的DVWA入门靶场实战(二)继续:

1. Weak Session IDs(脆弱的 Session)

与Cookie相比,Session是保存在服务器中的。用户登录后,服务器会创建一个session id给用户,之后每次访问页面携带session,服务器就知道你是谁了。

常规访问的流程:用户拿到服务器发过来的session id之后,就会加密保存到cookies上,只要cookies随着http请求发送服务器,服务器就知道你是谁了。如果session id过于简单,就会在生命周期内被伪造、窃取、利用,就可以伪装成合法用户访问该网站,而不再需要账户和密码。

也就是说,攻击者只需要拿到session id就可以绕过登录限制,直接进入用户登录状态的网站。

1.1 Low级别

看一下Low级别的源码:

if ($_SERVER['REQUEST_METHOD'] == "POST") {
	if (!isset ($_SESSION['last_session_id'])) {
		$_SESSION['last_session_id'] = 0;
	}
	$_SESSION['last_session_id']++;//自增1
	$cookie_value = $_SESSION['last_session_id'];
	setcookie("dvwaSession", $cookie_value);//存到cookie
}

可以看到session id的规律是每次生成都会自增1,然后存到cookie。打开Burp发送请求-抓包:

可以看到dvwaSession的值为1,然后再抓一次包,dvwaSession的值就是2了,每次都递增1:

1.2 Medium级别

Low级别和Medium级别的源码区别:

if ($_SERVER['REQUEST_METHOD'] == "POST") {
	$cookie_value = time();
	setcookie("dvwaSession", $cookie_value);

本级别利用时间戳函数time()生成dvwaSession的值,也是有规律的值,可以通过在线时间戳转换工具生成时间戳,其他流程同Low级别一样,没有其他差别。

1.3 High级别

看一下本级别的源码:

if ($_SERVER['REQUEST_METHOD'] == "POST") {
	if (!isset ($_SESSION['last_session_id_high'])) {
		$_SESSION['last_session_id_high'] = 0;
	}
	$_SESSION['last_session_id_high']++;
	$cookie_value = md5($_SESSION['last_session_id_high']);
	setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);//设置了时间和请求域HTTP_HOST,只能在/vulnerabilities/weak_id/目录下使用
}

通过源码发现,session id的生成方式是:先将session id自增,然后进行MD5加密,最后设置了Cookie的有效期是当前的时间加上1个小时,而且还设置了请求域。基本操作和Low级别无异,找个MD5加解密网站解密就可以得到session id了。

1.4 Impossible级别

查看本级别牢不可破的源码:

if ($_SERVER['REQUEST_METHOD'] == "POST") {
	$cookie_value = sha1(mt_rand() . time() . "Impossible");
	setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], true, true);

sha1加密(随机会话id+ 时间戳 +”Impossible” ),当前时间+1小时+路径限制+请求域+http/https

2. XSS(Reflected)反射型跨站脚本

反射型跨站脚本是一种非持久性攻击,攻击者构造一个包含恶意脚本的URL,将其作为参数传递给web程序,然后诱使用户点击该链接来执行攻击。

2.1 Low级别

看一下本级别的源码:

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只是简单的判断是否存在和是否为空,而且使用GET方式请求,没有其他的检测和过滤措施,所以存在XSS漏洞。搜索框中输入脚本检测一下,如果弹窗成功弹出,就说明存在漏洞。

<script>alert(1)</script>

可以看到,页面弹窗成功弹出了:

2.2 Medium级别

看一下本级别的源码:

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>";

从源码中看到,str_replace函数过滤了<script>标签(替换为空),也是可以绕过的:

  • 大小写转换绕过
  • 双写嵌套绕过
  • 改用其他标签

正则没有匹配到大写的script标签,大小写转换绕过检测:

<Script>alert(1)</script>

双写嵌套绕过payload:

<sc<script>ript>alert(1)</script>

改用其他标签构造payload:

<iframe onload=alert(1)>
<img src=y onerror=alert(1)>

2.3 High级别

本级别的源码如下:

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>";
}

可以看到,正则还是匹配了<script>标签,不区分大小写的,大小写转换绕过和双写嵌套都不行了,但还是可以通过其他标签来绕过,参考Medium级别的payload。

2.4 Impossible级别

看一下本级别无懈可击的源码:

// 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();

htmlspecialchars()函数把name变量转换为HTML实体并输出了,没有什么措施可以绕过。

3. XSS(Stored)存储型跨站脚本

与反射型XSS不同的是,存储型XSS是一种持久型XSS,攻击者将恶意脚本注入到Web应用程序服务端的某个存储区域,服务器响应给用户页面时,将恶意脚本当做有效数据插入到页面中,浏览器执行该响应的页面,就会把恶意脚本一起执行了。

3.1 Low级别

本级别的源码如下:

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();
}

源码中,stripslashes函数对message变量进行了过滤,但是没有对name做任何检测,

trim函数TRIM 函数是一个字符串处理函数,用于移除字符串两端(首尾)的空格或其他预定义字符;stripslashes函数用于移除字符串中由 addslashes() 添加的反斜杠转义字符;

mysql_real_escape_string函数用于转义 SQL语句中使用的特殊字符。

看一下页面,我们随意输入文本观察页面变化:

输入了xss,发现直接在页面输出了,那么输入脚本看看:

<script>alert(1)</script>

还是和反射型一样弹出了1,但是不同的是,我们输入的内容直接插入到了数据库中:

3.2 Medium级别

本级别的源码如下:

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();
}

本级别源码中,message参数使用了htmlspecialchars函数进行编码,所以无法通过这个参数项进行XSS注入了,但是对于name参数中script标签被过滤了,仍然可以进行XSS注入,方法和反射型类似。

strip_tags()函数用于从字符串中移除所有HTML、XML和PHP标签,只保留纯文本内容,但可以使用<b>标签或者是<a>标签;

addslashes()函数用于返回在预定义的字符(单引号、双引号、反斜杠\、NULL)前添加反斜杠的字符串;

htmlspecialchars函数用于将特定的预定义字符(如 <>&" 和 ')转换为HTML实体,以防止在网页上显示时,这些字符被浏览器解释为HTML代码。

接下来就可以通过name参数进行注入了,不过还有一个问题,你会发现name参数会有长度限制,那么我们改一下index.php文件,找到<input name=,修改maxlength属性改为100就可以了。

3.3 High级别

本级别的源码如下:

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参数仍然不能XSS注入,name参数也不能使用双写嵌套、大小写转换了,但是还可以通过其他标签来注入,这一点和反射型类似,就不多说了。

3.4 Impossible级别

一如既往的不可能:

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参数的过滤一样了,而且还增加了token防止CSRF攻击。

4. XSS(DOM)DOM 型跨站脚本

DOM型XSS是一种特殊的反射型XSS,注入点在于客户端而非服务端,且不需要服务端的参与,完全是客户端(浏览器)自己的事。攻击者通过操作页面的DOM节点,诱使浏览器DOM解析,从而执行恶意脚本。

4.1 Low级别

先看一下源码:

<div class="body_padded">
	<h1>Vulnerability: DOM Based Cross Site Scripting (XSS)</h1>

	<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>
<?php

# No protections, anything goes

?>

可以看到无任何防范措施,在URL中直接注入即可:

default=<script>alert(1)</script>

4.2 Medium级别

源码如下:

// 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变量进行了<script>标签过滤,但是仍然可以使用其他标签配合事件来实现弹窗的功能,如果说SQL注入攻击是构造合法有效的SQL语句,那么DOM型的XSS攻击就需要构造合法有效的HTML标签了。

闭合</option></select>标签可以进行XSS注入,然后通过<img>标签弹窗:

default=English</option></select><img src='y' onerror='alert(1)'>

或者直接使用input标签中的点击事件来触发XSS,需要点击input输入框:

default=English<input onclick=alert('1') />

4.3 High级别

本级别的源码如下:

// 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的值只能是选项菜单的几项,如果不是URL就重置为default=English。

可以使用#符号来绕过限制:

default=English#</option></select><img src=y onload=alert(1)/>

也可以使用&连接符来绕过:

default=English&xss=</option></select><img src=y onerror=alert(1)>
default=English&xss=<input onclick=alert(1) />

4.4 Impossible级别

无懈可击的源码:

<?php

# Don't need to do anything, protection handled on the client side

?>

源码中说保护措施写在了客户端里,那我们看一下index.php里的代码:

# For the impossible level, don't decode the querystring
$decodeURI = "decodeURI";
if ($vulnerabilityFile == 'impossible.php') {
	$decodeURI = "";
}

浏览器会对URL中输入的内容进行编码,也就是说我们注入的标签将会失效,从而有效的防止了XSS漏洞。

5. CSP Bypass(绕过内容安全策略)

CSP Bypass全称为Content Security Policy Bypass:绕过内容安全策略,也就是我们常说的白名单机制,用户只需配置参数,由浏览器来执行。

5.1 Low级别

本级别的源码如下:

$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com www.toptal.com example.com code.jquery.com https://ssl.google-analytics.com https://digi.ninja ;"; 
header($headerCSP);

if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
	<script src='" . $_POST['include'] . "'></script>
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
	<p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p>
	<input size="50" type="text" name="include" value="" id="include" />
	<input type="submit" value="Include" />
</form>

通过源码中可以看到白名单的应用:

  • self
  • https://pastebin.com
  • hastebin.com
  • www.toptal.com
  • example.com
  • code.jquery.com
  • https://ssl.google-analytics.com
  • https://digi.ninja

我们试一下https://pastebin.com这个网站,是一个快速分享文本的网站,操作流程:

打开https://pastebin.com主页,在New Paste的输入框输入想执行的脚本(比如alert(1)),点击Create New Paste,点击Raw,就会生成一个网址https://pastebin.com/r3a46A8r,复制到dvwa的输入框中:

然后点击Include,就会出现弹窗,如果没有弹出,说明这是个国外的网站没有响应,可以F12看一下:

5.2 Medium级别

看一下本级别的源码:

$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";

header($headerCSP);

// Disable XSS protections so that inline alert boxes will work
header ("X-XSS-Protection: 0");

# <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>

if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
	" . $_POST['include'] . "
";
}

HTML的script-src属性用于定义脚本的加载源,主要作用是控制脚本来源和管理内联脚本:

  • unsafe-inline:允许使用内联资源,比如<script>标签和事件监听函数
  • nonce-source:允许特定的内联脚本资源执行,但会指定一个唯一、随机生成的字符串值,只有携带这个值才会执行
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>

5.3 High级别

看一下本级别的源码:

<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";

header($headerCSP);

?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
	" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
	<p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
	<p>1+2+3+4+5=<span id="answer"></span></p>
	<input type="button" id="solve" value="Solve the sum" />
</form>

<script src="source/high.js"></script>
';

从源码可以看到,白名单就只有self,即本页面加载的脚本。看一下引入的脚本high.js:

function clickButton() {
    var s = document.createElement("script");
    s.src = "source/jsonp.php?callback=solveSum";
    document.body.appendChild(s);
}

function solveSum(obj) {
	if ("answer" in obj) {
		document.getElementById("answer").innerHTML = obj['answer'];
	}
}

var solve_button = document.getElementById ("solve");

if (solve_button) {
	solve_button.addEventListener("click", function() {
		clickButton();
	});
}

可以看到high.js脚本对id为solve的input输入框做了处理,触发了clickButton()方法。

clickButton()方法的功能:

  • 创建一个script标签;
  • src指向了source/jsonp.php?callback=solveSum;
  • 调用appendChild()函数将src添加到DOM中。

solveSum函数对id为answer的元素也做了处理,script把远程加载的answer值当做js代码执行,结果就会输出到页面。然后打开Burp发送改请求-抓包看看:

点击Solve the sum按钮可以看到生成的URL,我们可以改成alert(1)函数试试:

jsonp.php?callback=alert(1)

结果就是把返回值直接输出在了页面:

此时如果alert被调用的话,就会出现弹窗了,那么怎么才能调用呢?看一下源码:

if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
	" . $_POST['include'] . "
";
}

这段代码的意思是,如果URL指定了include参数,将会直接插入到DOM中,那么就可以构造弹窗代码:

include=<script src=source/jsonp.php?callback=alert(1)></script>

安装hackbar插件,然后提交POST请求,快捷键Alt+X执行就出现弹窗了:

5.4 Impossible级别

impossible.php源码和high.php基本无异,impossible.js也无差别,主要是jsonp的代码发生了变化:

header("Content-Type: application/json; charset=UTF-8");

$outp = array ("answer" => "15");

echo "solveSum (".json_encode($outp).")";

这里只输出了solveSum,不能使用callback参数了,指定了要输出的函数,这样就没办法了。

6. JavaScript Attacks(JS 攻击)

JavaScript Attacks也就是通过JavaScript语言执行非法的恶意操作。

6.1 Low级别

看一下本级别的源码:

$page[ 'body' ] .= <<<EOF
<script>

/*
MD5 code from here
https://github.com/blueimp/JavaScript-MD5
*/

!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[14+(r+64>>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,d=v,h=m,g=f(g=f(g=f(g=f(g=c(g=c(g=c(g=c(g=u(g=u(g=u(g=u(g=o(g=o(g=o(g=o(g,v=o(v,m=o(m,l=o(l,g,v,m,n[e],7,-680876936),g,v,n[e+1],12,-389564586),l,g,n[e+2],17,606105819),m,l,n[e+3],22,-1044525330),v=o(v,m=o(m,l=o(l,g,v,m,n[e+4],7,-176418897),g,v,n[e+5],12,1200080426),l,g,n[e+6],17,-1473231341),m,l,n[e+7],22,-45705983),v=o(v,m=o(m,l=o(l,g,v,m,n[e+8],7,1770035416),g,v,n[e+9],12,-1958414417),l,g,n[e+10],17,-42063),m,l,n[e+11],22,-1990404162),v=o(v,m=o(m,l=o(l,g,v,m,n[e+12],7,1804603682),g,v,n[e+13],12,-40341101),l,g,n[e+14],17,-1502002290),m,l,n[e+15],22,1236535329),v=u(v,m=u(m,l=u(l,g,v,m,n[e+1],5,-165796510),g,v,n[e+6],9,-1069501632),l,g,n[e+11],14,643717713),m,l,n[e],20,-373897302),v=u(v,m=u(m,l=u(l,g,v,m,n[e+5],5,-701558691),g,v,n[e+10],9,38016083),l,g,n[e+15],14,-660478335),m,l,n[e+4],20,-405537848),v=u(v,m=u(m,l=u(l,g,v,m,n[e+9],5,568446438),g,v,n[e+14],9,-1019803690),l,g,n[e+3],14,-187363961),m,l,n[e+8],20,1163531501),v=u(v,m=u(m,l=u(l,g,v,m,n[e+13],5,-1444681467),g,v,n[e+2],9,-51403784),l,g,n[e+7],14,1735328473),m,l,n[e+12],20,-1926607734),v=c(v,m=c(m,l=c(l,g,v,m,n[e+5],4,-378558),g,v,n[e+8],11,-2022574463),l,g,n[e+11],16,1839030562),m,l,n[e+14],23,-35309556),v=c(v,m=c(m,l=c(l,g,v,m,n[e+1],4,-1530992060),g,v,n[e+4],11,1272893353),l,g,n[e+7],16,-155497632),m,l,n[e+10],23,-1094730640),v=c(v,m=c(m,l=c(l,g,v,m,n[e+13],4,681279174),g,v,n[e],11,-358537222),l,g,n[e+3],16,-722521979),m,l,n[e+6],23,76029189),v=c(v,m=c(m,l=c(l,g,v,m,n[e+9],4,-640364487),g,v,n[e+12],11,-421815835),l,g,n[e+15],16,530742520),m,l,n[e+2],23,-995338651),v=f(v,m=f(m,l=f(l,g,v,m,n[e],6,-198630844),g,v,n[e+7],10,1126891415),l,g,n[e+14],15,-1416354905),m,l,n[e+5],21,-57434055),v=f(v,m=f(m,l=f(l,g,v,m,n[e+12],6,1700485571),g,v,n[e+3],10,-1894986606),l,g,n[e+10],15,-1051523),m,l,n[e+1],21,-2054922799),v=f(v,m=f(m,l=f(l,g,v,m,n[e+8],6,1873313359),g,v,n[e+15],10,-30611744),l,g,n[e+6],15,-1560198380),m,l,n[e+13],21,1309151649),v=f(v,m=f(m,l=f(l,g,v,m,n[e+4],6,-145523070),g,v,n[e+11],10,-1120210379),l,g,n[e+2],15,718787259),m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,d),m=t(m,h);return[l,g,v,m]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function h(n){return a(i(d(n),8*n.length))}function l(n,t){var r,e,o=d(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),e+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);

	function rot13(inp) {
		return inp.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
	}

	function generate_token() {
		var phrase = document.getElementById("phrase").value;
		document.getElementById("token").value = md5(rot13(phrase));
	}

	generate_token();
</script>
EOF;

index.php源码:

if ($_SERVER['REQUEST_METHOD'] == "POST") {
	if (array_key_exists ("phrase", $_POST) && array_key_exists ("token", $_POST)) {

		$phrase = $_POST['phrase'];
		$token = $_POST['token'];

		if ($phrase == "success") {
			switch( dvwaSecurityLevelGet() ) {
				case 'low':
					if ($token == md5(str_rot13("success"))) {
						$message = "<p style='color:red'>Well done!</p>";
					} else {
						$message = "<p>Invalid token.</p>";
					}
					break;
				case 'medium':
					if ($token == strrev("XXsuccessXX")) {
						$message = "<p style='color:red'>Well done!</p>";
					} else {
						$message = "<p>Invalid token.</p>";
					}
					break;
				case 'high':
					if ($token == hash("sha256", hash("sha256", "XX" . strrev("success")) . "ZZ")) {
						$message = "<p style='color:red'>Well done!</p>";
					} else {
						$message = "<p>Invalid token.</p>";
					}
					break;
				default:
					$vulnerabilityFile = 'impossible.php';
					break;
			}
		} else {
			$message = "<p>You got the phrase wrong.</p>";
		}
	} else {
		$message = "<p>Missing phrase or token.</p>";
	}
}

可以看到token是调用了generate_token()函数里的md5(rot13(‘phrase’))生成的,且是在前端生成的,那么根据页面的提示输入success,如果直接输入则提示token无效,F12打开控制台执行md5(rot13(‘success’))函数获取到最新的token:

然后将token复制到Burp的参数里:

然后放包,就发现页面成功的信息了:

6.2 Medium级别

本级别的源码如下:

<?php
$page[ 'body' ] .= '<script src="' . DVWA_WEB_PAGE_TO_ROOT . 'vulnerabilities/javascript/source/medium.js"></script>';
?>

源码中引入了medium.js,看一下脚本:

function do_something(e){for(var t="",n=e.length-1;n>=0;n--)t+=e[n];return t}
setTimeout(function(){do_elsesomething("XX")},300);
function do_elsesomething(e){document.getElementById("token").value=do_something(e+document.getElementById("phrase").value+"XX")}

通过源码发现token通过do_elsesomething函数进行反转处理,然后前后都加了“XX”,打开Burp发送改请求抓包,看一下效果:

那我们输入的是success,那么token就应该是XXsseccusXX,那我们在Burp里改一下就可以了:

6.3 High级别

看一下本级别的源码:

<?php
$page[ 'body' ] .= '<script src="' . DVWA_WEB_PAGE_TO_ROOT . 'vulnerabilities/javascript/source/high.js"></script>';
?>

跟进high.js脚本看一下,发现是js混淆了,那么找个在线工具还原一下就可以了:在线解码工具

DVWA源码里也提供了解码后的文件:high_unobfuscated.js,解码之后发现了这段代码:

function do_something(e) {
    for (var t = "", n = e.length - 1; n >= 0; n--) t += e[n];
    return t
}
function token_part_3(t, y = "ZZ") {
    document.getElementById("token").value = sha256(document.getElementById("token").value + y)
}
function token_part_2(e = "YY") {
    document.getElementById("token").value = sha256(e + document.getElementById("token").value)
}
function token_part_1(a, b) {
    document.getElementById("token").value = do_something(document.getElementById("phrase").value)
}
document.getElementById("phrase").value = "";
setTimeout(function() {
    token_part_2("XX")
}, 300);
document.getElementById("send").addEventListener("click", token_part_3);
token_part_1("ABCD", 44);

这里会发现do_something还是反转操作,token_part_2(“XX”)函数会有300毫秒的延迟,所以会先执行token_part_1(“ABCD”, 44),token_part_3()函数和click事件一起执行:

首先在输入框中输入“success”,F12进入浏览器控制台,依次执行如下函数:

token_part_1("ABCD",44);
token_part_2("XX");

然后继续点击提交就可以了。

6.4 Impossible级别

本级别直接没有输入框了,无可能的操作:

You can never trust anything that comes from the user or prevent them from messing with it and so there is no impossible level.


免责声明:


1. 一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。

2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。

3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
觉得有帮助可以赞赏本文哦~万分感谢!
文章:DVWA入门靶场实战(三)
作者:沛旗
链接:https://www.peiqiblog.com/article/5375/
版权声明::本博客站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦~
暂无评论

发送评论(禁止发表一切违反法律法规的敏感言论) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇