XSS | DOM 型 XSS 攻击

关注这个漏洞的其他相关笔记:XSS 漏洞 - 学习手册-CSDN博客

0x01:DOM 型 XSS —— 理论篇

DOM 全称 Document Object Model,使用 DOM 可以使程序和脚本能够动态访问和更新文档的内容、结构及样式。

DOM 型 XSS 是一种特殊类型的反射型 XSS,它是基于 DOM 文档对象模型的一种漏洞。

0x0101:知识前导 - DOM

HTML 的标签都是节点,而这些节点组成了 DOM 的整体结构 —— 节点树。通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。 所有 HTML 元素(节点)均可被修改,也可以创建或者删除节点。

比如下面这个 HTML 代码:

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <title>网页标题</title>
 </head>
 <body>
     <h1>我的标题</h1>
     <a href="">我的链接</a>
 </body>
 </html>

其对应的 HTML DOM 树的结构如下图所示:

在网站页面中有许多元素,当页面到达浏览器,浏览器会为页面创建一个顶级的 Document object 文档对象,接着生成各个子文档对象,每个页面元素对应一个文档对象,每个文档对象包含属性、方法和事件。

可以通过 JS 脚本对文档对象进行编辑,从而修改页面的元素。也就是说,客户端的脚本程序可以通过修改 DOM 动态修改页面内容,从客户端获取 DOM 中的数据并在本地执行。

由于 DOM 是在客户端修改节点的,所以基于 DOM 型的 XSS 漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。

0x0102:DOM 型 XSS 攻击流程

常见的攻击方式: 用户请求一个经过专门设计的 URL,它由攻击者发布,而且其中包含 XSS 代码。服务器的响应不会以任何形式包含攻击者的脚本。当用户的浏览器处理这个响应时,DOM 对象就会处理 XSS 代码,导致存在 XSS 漏洞。

其攻击流程如下图所示:

其整体攻击流程与反射型 XSS 很相似,只不过是因为 DOM 型 XSS 形成的原因比较特别,发现它的安全专家专门提出了这种类型的 XSS。出于历史原因,就把它单独作为一个分类了。

0x02:DOM 型 XSS —— 实战篇

实验工具准备

实验环境的搭建流程我放在了 DOMBasedXSSLab.zip 中了,这里就不多说了,下面直接开始演示。

0x0201:DOM 型 XSS 攻击

在浏览器的导航栏中输入下面的网址,访问实验环境:

 http://127.0.0.1/DOMBasedXSSLab/

可以发现页面发生了跳转,跳转到了一个 404 Not Found 的页面。值得注意的是,该页面回显的 404 - Page XXX Not Found 中的 XXX 部分的内容似乎是通过浏览器 URL 中的 error 参数控制的。

我们可以修改一下导航栏中 error 字段的内容,并重新访问:

 http://127.0.0.1/DOMBasedXSSLab/404.html?error=Blue17

可以发现,error 字段的内容果然会直接回显回页面中,我们右击页面查看网页源码,看看回显的位置:

发现我们传递的参数直接回显在了 <h1> 标签中,那么攻击者可以尝试构造下面的 Payload,来攻击用户:

 http://127.0.0.1/DOMBasedXSSLab/404.html?error=<img src=1 onerror="alert(/You've Been Tricked/)" hidden/>

可以看到,页面成功加载了攻击者传入的 XSS 代码并运行。如果点击了 “确定” 按钮,可以看到,页面基本没有啥影响(弹窗只是为了演示脚本确实被执行了,真攻击没人给你弄这种弹窗):

至此,一个 DOM 型 XSS 攻击的全流程已经演示完毕了。整体流程和反射型其实是差不多的,主要是代码处理方面的问题,反射型 XSS 是后端语言处理用户提交的数据后,将 XSS 攻击代码携带进返回包中传递给客户端;而 DOM 型则是利用用户客户端的 JavaScript 脚本进行触发的,后端返回的数据包中并不包含 XSS 攻击代码,如下图所示:

可以发现,后端返回的数据包中只有页面标签的布局,<h1> 标签中是没有任何内容的,这符合了我们上面讲的 DOM 型 XSS,后端返回的数据包中不包含 XSS 攻击代码的特点。

0x0202:DOM 型 XSS 代码分析

下面是触发 DOM 型 XSS 漏洞的关键代码:

 <h1 id="dom_output"></h1>
 <script>
 const urlParams = new URLSearchParams(window.location.search); // 获取链接中 ? 号后面参数的部分
 if (urlParams.has('error')) { // 如果用户传递了 error 参数
   const errorInfo = urlParams.get('error'); // 获取 error 参数的内容
   document.getElementById("dom_output").innerHTML = "404 - Page " + errorInfo + " Not Found 未找到"; // 输出回标题
 }  else { // 如果用户没有传递 error 参数
   document.getElementById("dom_output").innerHTML = "404 - Page Not Found 未找到";  // 输出回标题
 }
 </script>

DOM 型 XSS 程序只有 HTML 代码,并不存在服务器端代码,所以此程序并没有与服务器端进行交互,是一个纯粹的运行在客户端的 JavaScript 脚本代码触发的 XSS 漏洞。

用户访问实验环境后,会跳转到 404 页面,并向该页面传递参数 error=xxxurlParams 识别用户传递过来的参数并进行保存,如果用户传递了 ?error=xxx,则获取 xxx 具体的内容,并通过 document.getElementById("dom_output").innerHTML 的方式,找到 iddom_output 的标签(也就是 <h1> 标签),将用户传递过来的参数拼接并回显。如果用户没有传递 error 参数,则回显默认的内容:404 - Page Not Found 未找到

程序逻辑很简单,就是获取 error 字段的内容并回显,没有做任何过滤,导致了 XSS 漏洞。

当用户对 error 传入 <img src=1 onerror="alert(/You've Been Tricked/)" hidden/> 时, 输出到 <h1> 标签中的内容实际是:

 <h1>404 - Page <img src=1 onerror="alert(/You've Been Tricked/)" hidden/> Not Found 未找到</h1>

此 HTML 代码中包含了一个 <img> 图片标签,链接到地址 1 的图片,这个图片必然不存在,所以导致图片加载错误触发了 onerror 部分的内容,该部分又是一个 JavaScript 代码,此代码会引起浏览器的弹窗,而末尾的 hidden 仅仅是为了隐藏 <img> 标签,让其在页面上不那么显眼而已。

0x03:DOM 型 XSS —— 后记

在构造攻击语句的时候,笔者一开始并没有想用 <img> 标签来触发,笔者一开始构造的链接如下:

 http://127.0.0.1/DOMBasedXSSLab/404.html?error=<script>alert(/You've Been Tricked/)</script>

可以发现,JavaScript 脚本被成功内嵌进了页面,但是却并未被执行。笔者的思考是:由于浏览器解析网页的顺序是从上往下的,所以其执行顺序如下图所示(不知道对不对,反正笔者把自己说服了):

下面是文心一言给的参考中,我觉得最符合情况的一条:

浏览器 DOM 解析和渲染机制 当浏览器解析 HTML 文档时,它会识别 <script> 标签并尝试执行其中的脚本。但是,当脚本是通过 JavaScript 动态添加到 DOM 中时,浏览器会采取不同的策略。特别是,当脚本内容通过 innerHTMLdocument.write() 或其他类似方法动态添加到文档中的,浏览器不会立即执行这些脚本。这是因为浏览器需要区分 “正常的” HTML 解析过程中加载的脚本和后来通过脚本动态添加的脚本。

0x04:参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SRC_BLUE_17

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值