DVWA下的XSS通关(存储型) – 作者:fu福lin林

知道这里的大佬很多,我这种小儿科难入法眼,我只是记录下自己的学习过程,编写自己的DVWA通关手册,最近很忙,但不能放弃我的目标,加油!

xss的介绍

XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器上执行,需要强调的是,XSS不仅仅限于JavaScript,还包括flash等其它脚本语言。根据恶意代码是否存储在服务器中,XSS可以分为存储型的XSS与反射型的XSS。DOM型的XSS由于其特殊性,常常被分为第三种,这是一种基于DOM树的XSS。例如服务器端经常使用document.boby.innerHtml等函数动态生成html页面,如果这些函数在引用某些变量时没有进行过滤或检查,就会产生DOM型的XSS。DOM型XSS可能是存储型,也有可能是反射型。

XSS利用的常见用途:
盗取用户cookies、劫持会话、流量劫持、网页挂马、DDOS、提升权限…

存储XSS:Stored Cross Site Scripting

存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie等。

1、Low Stored XSS Source(低难度的)

<?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(string,charlist)函数移除字符串两侧的空白字符或其他预定义字符,预定义字符包括\0、\t、\n、\x0B、\r以及空格,可选参数charlist支持添加额外需要删除的字符。

mysqli_real_escape_string(string,connection)函数会对字符串中的特殊符号(\x00,\n,\r,\,’,”,\x1a)进行转义。

stripslashes(string)函数删除字符串中的反斜杠。

可以看到,对输入并没有做XSS方面的过滤与检查,且存储在数据库中,因此这里存在明显的存储型XSS漏洞。经典payload:<script>alert(/xss/)</script>。

上操作:1603782555_5f97c79bdc32432ba96f1.png!small?1603782520463

其实应该在Message标签里填写xss攻击的payload,但我偏不在那里填,套用李云龙团长一句名言:“他娘的,从哪儿突围不是突围啊”。Name标签里填不下去,说明肯定有所限制,那就F12看看

1603783145_5f97c9e93004b0047db63.png!small?1603783108996

此时有两种办法:

第一种:原地修改maxlength的值,改10为100

1603783311_5f97ca8f5a5febf73cdfb.png!small?1603783274903

1603783446_5f97cb161bdcadeabb183.png!small?1603783409769

接下来,在message标签里随意填写内容,提交请求

1603783802_5f97cc7a3dc4e1a3ddea8.png!small?1603783765654

burpsuite抓包看看:

1603783973_5f97cd250f1cd6489cb28.png!small?1603783936871

第二种:利用burpsuite

1603784107_5f97cdab42bf87aa4eef1.png!small?1603784071005

1603784695_5f97cff77d430ca380c77.png!small?1603784659063

输入攻击payload,name标签里输入<script>alert(/xss/)</script>,message标签里输入1,提交请求

1603784784_5f97d050a7ad3431a86bb.png!small?1603784748425

直接在这个报文里修改攻击payload,让它完整

1603785684_5f97d3d4c6fb566a67573.png!small?1603785648296

然后放行这个请求

1603784935_5f97d0e76f2747ea6bba3.png!small?1603784903542

回到浏览器,看结果

1603785673_5f97d3c9ddd6e2e3213d9.png!small?1603785637651

因为这个是low级别的,基本零防护,所以随便玩,没有人规定一定要在message标签里填写攻击payload,当然message里填写的话,就没这么多弯路。

2、Medium Security Level(中难度的)

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

相关函数介绍

strip_tags()函数剥去字符串中的HTML、XML以及PHP的标签,但允许使用<b>标签。

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

可以看到,由于对message参数使用了htmlspecialchars函数进行编码,因此无法再通过message参数注入XSS代码,但是对于name参数,只是简单过滤了<script>字符串,仍然存在存储型的XSS。

依旧还有很多办法,感觉和反射型XSS一样的

1.双写绕过

Burpsuite抓包改name参数为:

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

2.大小写混淆绕过

Burpsuite抓包改name参数为<ScRipt>alert(/xss/);</ScRipt>

3.使用非 script 标签的 xss payload:

例如:img标签:

Burpsuite抓包改name参数为<img src=1 onerror=alert(/xss/)>

其他标签和利用还有很多很多…

操作起来:在name标签里填写数字1,在massage标签里填写<script>alert</script>,提交请求:

1603787974_5f97dcc62a966448093f8.png!small?1603787937606

1603788060_5f97dd1cf190a03a6fba0.png!small?1603788024480

失败,明显不行,继续验证一波,来个双写绕过试试,以及其它的

1603788210_5f97ddb260cfdef6c8573.png!small?1603788173912

1603788233_5f97ddc94bb3dbfe9060f.png!small?1603788196690

大小写混合的;

1603788418_5f97de8274476ec6b25d0.png!small?1603788382038

1603788435_5f97de93e08ac335610a2.png!small?1603788399331

非<script>标签的:

1603788522_5f97deea559410e4b3a9a.png!small?1603788485730

1603788539_5f97defbb67e05f601fde.png!small?1603788503125

实践出真知,说明htmlspecialchars函数起效了,message标签已经无法注入xss攻击。那么只能攻击name标签了。

直接利用burpsuite工具:先双写绕过1603789395_5f97e25347d28502fcf80.png!small?1603789358841

1603789805_5f97e3edcdcce2bd46a7f.png!small?1603789769660

1603789832_5f97e4089ef0ec2d4196d.png!small?1603789796260

再来试试大小写混合:

1603789926_5f97e466cedc7a79ad2a1.png!small?1603789890291

1603790483_5f97e6932b6700bb01449.png!small?1603790446622

1603790496_5f97e6a04afa4afc543ce.png!small?1603790459728

最后再来个非<script>标签的:<img scr=1 onerror=alert(/xss/)>

1603791137_5f97e9210e80636c3d49a.png!small?1603791100675

1603793435_5f97f21b6be99dd319b71.png!small

1603793346_5f97f1c25cca3f3c73f05.png!small?1603793309967

搞定medium级别的,继续下一关,要high起来

3、High Security Level(高难度的)

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

?>

可以看到,这里使用正则表达式过滤了<script>标签,但是却忽略了img、iframe等其它危险的标签,因此name参数依旧存在存储型XSS。

上操作,其实medium级别最后的一个操作跟这个一样:

<img>标签:

1603794444_5f97f60c3fa43558dc34d.png!small?1603794407608

1603794460_5f97f61c1191d2f20ecb3.png!small?1603794423501

1603794500_5f97f6441f3c111179320.png!small?1603794463533

<iframe>标签:

1603805563_5f98217b413bb90483566.png!small?1603805526758

1603805662_5f9821de5c6158d0e1f36.png!small?1603805625949

1603805694_5f9821feccf698351a4ad.png!small?1603805658228

使用DATA URL:

<object data=”data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=”></object>

其中的“PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=”就等同于“<script>alert(‘xss’)</script>“。

1603805916_5f9822dce64cf228f9341.png!small?1603805880276

1603806058_5f98236a593768c9e31b5.png!small?1603806021822

1603806150_5f9823c6c624d6c051dd5.png!small?1603806114457

1603806185_5f9823e968348ba5660e5.png!small?1603806148790

对比反射型的xss,攻击套路真的是一模一样。接下来,看看Impossible级别的,以后针对存储型xss漏洞加固可以参考。

4、Impossible  Security Level(不可能的,安全级别最高)

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

?>

可以看到,通过使用htmlspecialchars函数将几种特殊字符转义为HTML实体,mysqli_real_escape_string函数对单引号’转义,防止进行SQL注入,彻底防治了存储型 XSS 的利用和危害。这段话可以做针对xss防护加固的建议。

来源:freebuf.com 2020-10-27 21:49:13 by: fu福lin林

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论