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:Reflected Cross Site Scripting

反射型XSS,非持久化,需要欺骗用户自己去点击带有特定参数的XSS代码链接才能触发引起(服务器中没有这样的页面和内容),一般容易出现在搜索页面。

1、Low Security Level:(低难度的)

<?php

// Is there any input?

if( array_key_exists( “name”, $_GET ) && $_GET[ ‘name’ ] != NULL ) {

// Feedback for end user

echo ‘<pre>Hello ‘ . $_GET[ ‘name’ ] . ‘</pre>’;

}

?>

可以看到,代码直接采用get方式传入了name参数,并没有任何的过滤与检查,存在明显的XSS漏洞。最普通的测试payload:

<script>alert(/xss/)</script> ,根据经验,一般有xss漏洞的,这个payload就可以试出来,试不出来的一般就没有xss漏洞了,当然也不是绝对,只是大多数情况而已。

操作很简单:

1603721167_5f96d7cf55c776ece61f4.png!small?1603721130463

提交后的结果:

1603721187_5f96d7e3030106e3518b8.png!small?1603721150271

可以看到url后面多了一个“尾巴”:?name=<script>alert(%2Fxss%2F)<%2Fscript>#,这个就是转义后的payload:<script>alert(/xss/)</script>。

1603721218_5f96d8020842696517c6d.png!small?1603721181192

1603721226_5f96d80a79d7785cb0506.png!small?1603721189538

那么说明,“%2F”此处表示的内容是“/”。之所以多此一举试这些,也是自己内心中有疑惑,同时得知一个小常识,请求的url中如果带有“%”,自己又看不懂,就可以尝试url解码一波,说不定就有惊喜出现,

通过burpsuite抓包:

1603721244_5f96d81c478873ea711fd.png!small?1603721207428

那么问题来了,burpsuite抓包里的url跟上面不一样,这里是“?name=%3Cscript%3Ealert%28%2Fxss%2F%29%3C%2Fscript%3E”,那框起来的部分也能url解码为相同的payload吗?继续解码看结果:

1603721258_5f96d82ab15ce6b5e8c44.png!small?1603721221764

1603721266_5f96d832d58d4f1249316.png!small?1603721229886

在burpsuite上的报文,结合这个字段转义前后,可以得出一个结论,这里的“%3C”表示的是“<”,而“%3E”表示的是“>”,“%28”表示的是“(”,“%29”表示的是“)”,“%2F”表示的是“/”。所以,“?name=<script>alert(%2Fxss%2F)<%2Fscript>#”与“?name=%3Cscript%3Ealert%28%2Fxss%2F%29%3C%2Fscript%3E”两个内容其实表示的是一样的东西,只是所展示的形式略有不同而已。

总结一下,其实low级别很简单,因为没有防护,所以随便玩,继续进行下一级挑战。

2、Medium Security Level(中难度的)

<?php

// 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

echo “<pre>Hello ${name}</pre>”;

}

?>

可以看到,这里对输入进行了过滤,使用str_replace函数将输入中的<script>替换为空,这种黑名单防护机制是可以被轻松绕过的。
①大小写绕过:<ScRipt>alert(/xss/)</ScRipt>

②双写方式绕过str_replace()函数:

<scr<script>ipt>alert(/xss/)</script>

③使用非script标签的xss payload:

img标签:
<img src=1 onerror=alert(‘xss’)>
iframe标签:
<iframe onload=alert(1)>
<iframe src=javascript:alert(‘xss’);height=0 width=0 /><iframe>
其他标签和利用还有很多很多….

看操作:

1603721366_5f96d896f06f8eed41e26.png!small?1603721330124

1603721374_5f96d89ebf88bf2d927b4.png!small?1603721337872

原因就是源码针对“<script>”字段进行过滤,所以payload就没法进行执行了。

但还是有办法对付的:

①大小写绕过:<ScRipt>alert(/xss/)</ScRipt>

1603721390_5f96d8ae0b160d54534ab.png!small?1603721353325

1603721397_5f96d8b52e7c3ede4ad6d.png!small?1603721360194

②双写方式绕过str_replace()函数:<scr<script>ipt>alert(/xss/)</script>

1603721416_5f96d8c8932dfc1bf1d93.png!small?1603721379699

③使用非script标签的xss payload:这种更绝,你过滤“<script>”,那我还不用它了。

1603721440_5f96d8e0ac1cc9f797ab6.png!small?1603721404322

1603721570_5f96d962d63bdcf1d5b34.png!small?1603721533972

思维一下子就活跃了,这种简单防护其实也没什么大用。继续下一关,Go!Go!Go!

3、High Security Level(高难度的)

<?php
// 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
echo “<pre>Hello ${name}</pre>”;
}
?>

可以看到,High Security Level的代码同样使用黑名单过滤输入,preg_replace() 函数用于正则表达式的搜索和替换,这使得双写绕过、大小写混淆绕过(正则表达式中i表示不区分大小写)不再有效。

虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件或者iframe等标签的src构造可利用的js代码。
1.使用img标签和其编码转换后的XSS payload:
<img src=1 onerror=alert(/xss/)>

img标签编码转换后的XSS payload例如:
<img src=1 onerror=eval(“\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29”)></img>
<img src=1 onerror=eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41))></img>
<imgsrc=1onerror=eval(“\u0061\u006c\u0065\u0072\u0074\u0028\u0027\u0078\u0073\u0073\u0027\u0029”)></img>

2.使用iframe标签:
<iframe onload=alert(/xss/)>
使用DATA URL进行XSS:
<object data=”data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=”></object>,其他的XSS payload,还有很多很多…

话不多说,上操作:

1603721652_5f96d9b4a995fbdeeeec6.png!small?1603721615784

1603721660_5f96d9bcb128202dfc8cf.png!small?1603721624318

1603721668_5f96d9c47eab6239e7a3f.png!small?1603721631644

使用非<script>标签的,居然可以,哈哈

1603721690_5f96d9da8c88aeff622da.png!small?1603721653779

1603721701_5f96d9e5c09af52e4d93d.png!small?1603721665104

小总结一波,就算把<script>过滤得死死的,但是我们还有其它标签,攻击效果仿佛更佳,至于Impossible 级别的,就不试了,攻不破的,它可以作为最佳加固方案参考。

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

<?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
echo “<pre>Hello ${name}</pre>”;
}
// Generate Anti-CSRF token
generateSessionToken();
?>

PHP htmlspecialchars()函数
把预定义的字符转换为HTML实体:
& (和号)成为 &
” (双引号)成为 “
‘ (单引号)成为 ‘//生效需要加ENT_QUOTES参数
< (小于)成为 <
> (大于)成为 >
可以看到,Impossible Security Level的代码使用htmlspecialchars函数把预定义的字符:& ” ‘ < >转换为HTML实体,防止浏览器将其作为HTML元素。从而防治了反射型XSS利用和危害。

5、写在最后

不懂之处就多操作,多练手,多思考,不管如何,我会坚持写下去,写出自己的学习过程,路过的大佬请随意喷,喷完请多多指教,谢谢!

来源:freebuf.com 2020-10-26 22:20:20 by: fu福lin林

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

请登录后发表评论