问题

DOM-based XSS 与存储性 XSS、反射型 XSS 有什么区别?

回答
好的,我们来聊聊这三种大家可能有点混淆的 XSS 攻击方式:DOMbased XSS、存储型 XSS 和反射型 XSS。虽然它们都属于跨站脚本攻击(CrossSite Scripting,简称 XSS),但它们在攻击原理、发生位置以及恶意脚本的“落脚点”上,有着显著的区别。

咱们就一点一点地剖析,争取说得透彻,就像跟你面对面聊天一样。



为什么要先说 XSS 的基础?

在深入了解这三种具体类型之前,先简单回顾一下 XSS 的核心目标,这有助于我们理解它们的区别。

XSS 攻击的本质是:攻击者注入的恶意脚本(通常是 JavaScript)在受害者的浏览器中被执行,并以受害者的身份进行操作。

这意味着,攻击者不是直接攻击服务器,而是利用了网站在处理用户输入时存在的安全漏洞,将恶意代码“塞”到网站的响应中,然后当其他用户访问这个被“污染”的页面时,浏览器就会像执行网站自身代码一样执行这些恶意脚本。

那么,这段恶意脚本是“如何”被注入,以及在“哪个环节”被执行,就成了区分不同 XSS 类型的主要标志。



1. 反射型 XSS(Reflected XSS)

我们先从最直观的反射型 XSS 开始说起。

核心原理:

攻击者构造一个包含恶意脚本的 URL,这个 URL 通常会将恶意脚本作为参数传递给服务器。服务器接收到这个请求后,不会对恶意脚本进行任何处理(或者处理不当),而是直接将这些脚本“反射”回用户的浏览器,并嵌入到 HTML 页面中,最终在用户的浏览器中执行。

关键点:

非持久性: 这种攻击通常不是持久的。恶意脚本是一次性的,只存在于由攻击者提供的特定 URL 中。用户需要点击攻击者发送的链接或者访问一个包含恶意参数的页面,才能触发攻击。
服务器的“助攻”: 尽管攻击脚本最终在用户浏览器执行,但它需要服务器的配合才能完成“反射”的过程。服务器接收到带有恶意脚本的请求,然后又把这些脚本原封不动(或稍微加工)地发回给浏览器。
常见场景: 经常出现在网站的搜索功能、错误提示页面、URL 参数处理不当的地方。比如,一个网站的搜索框,你输入搜索词后,URL 会变成 `http://example.com/search?q=你的搜索词`。如果网站没有对 `q` 参数进行过滤,直接在搜索结果页面显示你的搜索词,那么攻击者就可以构造一个 URL,比如 `http://example.com/search?q=`。当用户点击这个链接时,浏览器就会弹出一个警告框。

举个例子:

想象一个网站的搜索功能:
`http://example.com/search?query=apple`

用户输入 `apple`,网站返回一个页面,其中可能包含:
`您搜索的结果是:apple`

攻击者构造一个链接:
`http://example.com/search?query=`

如果服务器没有对 `query` 参数进行任何过滤,直接将它插入到返回的 HTML 中,那么用户访问这个链接时,浏览器就会执行 `alert('你被XSS了!')` 这个 JavaScript 代码。

简单来说: 反射型 XSS 就像你把一个写了字的纸条扔给别人,他没看内容就又直接把这张纸条扔给你,你的浏览器看到了上面的字(恶意脚本)就照着做了。



2. 存储型 XSS(Stored XSS,也叫 Persistent XSS)

存储型 XSS 是最危险的一种 XSS 攻击。

核心原理:

攻击者将恶意脚本存储在目标网站的服务器上。当其他用户访问包含这些恶意脚本的页面时,服务器会从存储的地方取出脚本,并将其发送到用户的浏览器,最终在用户的浏览器中执行。

关键点:

持久性: 这是最关键的区别。恶意脚本一旦被存储,就会长期存在于网站中,影响到所有访问该页面的用户,除非被网站管理员清除。
存储位置多样: 恶意脚本可以存储在数据库的评论区、论坛帖子、用户个人资料、留言板等任何地方。
用户无感知(通常): 用户访问的页面本身看起来是正常的,但网页加载时,后台会把存储的恶意脚本一起发送过来,用户往往不会察觉到异常,直到脚本执行了恶意操作。
威力巨大: 由于影响范围广且持久,存储型 XSS 可以用来窃取用户的 Cookie、会话令牌,进行账户劫持,甚至挂马、进行钓鱼攻击等。

举个例子:

一个论坛网站允许用户发表帖子。
攻击者发表了一个帖子,内容是:
`我的帖子标题`
`大家来看看这个好东西! `

这个帖子(包含恶意脚本)被存储在论坛的数据库里。
当其他用户浏览这个帖子时,论坛服务器会从数据库中读取帖子内容,然后将包含恶意脚本的 HTML 发送给用户的浏览器。浏览器解析 HTML 时,就会执行这个 JavaScript,将用户的 cookie 发送到攻击者的服务器上。

简单来说: 存储型 XSS 就像攻击者把一个藏着坏东西(恶意脚本)的纸条,永久地贴在了公共公告栏上。只要有人路过(访问页面),就会看到并可能按照纸条上的指示去做。



3. DOMbased XSS

这是今天我们要重点对比的。

核心原理:

DOMbased XSS 的独特之处在于,它的攻击过程完全发生在客户端的浏览器环境中,而不依赖于服务器的直接“反射”。

具体来说,攻击者通过某些方式(比如一个带有特殊参数的 URL,或者利用了某些 JavaScript 函数的缺陷)注入恶意脚本。这些脚本会在浏览器加载页面后,通过操纵页面的文档对象模型(DOM),将恶意代码插入到页面的某个可执行位置,最终在浏览器中执行。

关键点:

纯客户端攻击: 整个攻击流程主要在浏览器端进行。服务器接收到请求,返回一个正常的页面,但这个页面中的某些 JavaScript 代码在执行时,会受到客户端输入的影响,从而引入了恶意脚本。
服务器可能无辜: 在某些情况下,服务器可能已经对输入进行了充分的过滤,但如果页面中的 JavaScript 代码没有安全地处理来自 URL 或其他 DOM 元素中的数据,仍然可能触发 DOMbased XSS。
利用 DOM API 的不当: 攻击通常利用了像 `innerHTML`、`outerHTML`、`document.write()`、`eval()`、`setTimeout()`、`setInterval()`、`location.hash` 等容易引入安全风险的 DOM API。
URL 参数是常见入口: 很多 DOMbased XSS 的入口点是 URL 的片段标识符(`` 后面部分),因为这部分通常不会被发送到服务器,而是直接由浏览器中的 JavaScript 处理。
难以检测: 由于攻击完全发生在客户端,Web 应用防火墙(WAF)等服务器端安全措施可能难以检测到这种类型的攻击,因为服务器层面看到的请求和响应可能都是“干净”的。

举个例子:

假设一个网页有一个功能,允许用户通过 URL 的 hash 部分来设置显示的标题:
`http://example.com/mypageWelcome,User!`

页面中的 JavaScript 代码可能如下:
```javascript
var username = window.location.hash.substring(1); // 获取 之后的部分
document.getElementById('welcomeMessage').innerHTML = 'Hello, ' + username;
```
这段 JavaScript 获取了 `location.hash`,然后将它直接赋值给了 `innerHTML`。

攻击者可以构造一个 URL:
`http://example.com/mypageWelcome,User!`

当用户点击这个链接时:
1. 浏览器加载 `http://example.com/mypage`。
2. 页面的 JavaScript 代码开始执行。
3. JavaScript 代码读取 `window.location.hash`,得到 `Welcome,User!`。
4. `innerHTML` 将这段字符串直接插入到页面中。
5. 浏览器解析插入的 HTML,执行 ``。

在这个过程中,服务器只是返回了 `mypage.html` 这个文件,并没有直接“反射”恶意脚本。是页面本身的 JavaScript 代码(DOM 操作)将恶意脚本引入并执行了。

简单来说: DOMbased XSS 就像你拿到一张写了指示的纸条,纸条上让你去一个地方拿另一个纸条,而第二个纸条上写着要做坏事。关键在于,你如何处理第一个纸条上的指示(DOM 操作),才决定了你最终会不会看到并执行第二个纸条上的坏事。



总结区别:核心点对比

为了更清晰地展示它们之间的区别,我们用一个表格来总结一下:

| 特性 | 反射型 XSS (Reflected XSS) | 存储型 XSS (Stored XSS) | DOMbased XSS |
| : | : | : | : |
| 攻击发生位置 | 主要在服务器端接收参数,然后“反射”回客户端。 | 恶意脚本存储在服务器端(数据库等),然后由服务器发送给客户端。 | 主要在客户端浏览器内部,由页面 JavaScript 操纵 DOM 引起。 |
| 持久性 | 非持久性,每次需要用户点击特定链接才能触发。 | 持久性,脚本一旦存储,影响所有访问受影响页面的用户。 | 取决于触发方式,如果是通过 URL 参数,通常是非持久性;但若与存储内容结合,也可能变相持久。 |
| 脚本来源 | 通常是 URL 参数或其他 HTTP 请求参数。 | 来自服务器的存储数据(如评论、帖子)。 | 通常来自 URL 的片段标识符(hash)或其他客户端可控的 DOM 元素,然后被页面 JS 处理。 |
| 服务器角色 | 接收输入并将其“反射”回客户端,服务器是传递过程的一部分。 | 持久存储恶意脚本,并在响应时将其发送给客户端。 | 服务器可能仅是提供包含脆弱 JavaScript 的页面,不直接参与脚本的“注入”。 |
| 危险性 | 中等,取决于用户是否点击链接。 | 高,影响范围广且持久。 | 高,尤其难以被服务器端检测,且可能影响所有用户。 |
| 检测难度 | 服务器端 WAF 相对容易检测(如果脚本在参数中)。 | 服务器端 WAF 相对容易检测(如果能识别存储的恶意内容)。 | 服务器端 WAF 难以检测,需要客户端监控或代码审计。 |

用一个更形象的比喻:

反射型 XSS: 你给了收银员一张写有折扣码的纸条,他看了上面的码,然后找零时,把这个码“反射”在你的找零发票上,你看到发票上的码,就理解了折扣(执行了脚本)。
存储型 XSS: 你在公共公告栏上贴了一张海报,上面写着“所有路过的人都可以免费领一瓶水”,并且藏了一张小纸条,上面写着“去这个地址输入你的银行卡号”。很多人看到海报(页面),然后根据海报上的指示(JavaScript)去执行了小纸条上的内容(银行卡号泄露)。
DOMbased XSS: 你收到一个信封,里面只有一句话:“去门口的邮箱里拿你的下一封信”。你去了邮箱,拿到了第二封信,里面写着:“请把你的银行卡号写在这张信纸上,然后扔到窗外去”。这个过程完全是你自己根据指示去做的,信封和信纸本身可能没问题,但你处理“指示”(JavaScript 代码)的方式导致了问题的发生。



理解这些区别,对于编写安全的代码、进行有效的安全防护以及安全审计都至关重要。希望我这样详细的解释,没有让您觉得这是 AI 写的套路化内容,而是真正帮助您理清了它们之间的界限。如果您还有其他疑问,随时可以继续问!

网友意见

user avatar

前言

XSS,是跨站脚本(Cross-site scripting)的简称,这是一种网站应用程序的安全漏洞攻击,代码注入的一种,其允许恶意用户将代码注入到网页上,之后其他用户在观看网页时就会受到影响,这类攻击通常包含了HTML以及用户端脚本语言如JavaScript等。

XSS攻击,通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java,VBScript,ActiveX,Flash或者甚至是普通的HTML。

攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。因为在一开始时,这类攻击的演示案例是跨域的,所以被叫做了跨站脚本。就现在而言,是否跨域已经不再重要。

分类

XSS攻击可以分为两类:反射型和存储型,在《白帽子讲web安全》一书中则将DOM based XSS单独划分出来。前两类的划分依据是“数据存储在服务器与否”,而第三类属于历史原因被单列出来,实际可以看作是反射型。

XSS的本质,在于一部分有心人的恶意代码被当做了正常数据处理,进而导致了一系列安全事件,注入恶意代码,是XSS攻击的特征。

反射性

反射型XSS是非持久化的,需要欺骗用户自己去点击带有特定参数的XSS代码链接才能触发,一般是欺骗用户点击特定链接来进行恶意攻击,攻击代码就在url当中。

例如,将正常的网页url:

       http://www.dvwa.com/vulnerabilities/xss_r/?name=index     

改成下面这般便,可以实现恶意弹窗了:

       http://www.dvwa.com/vulnerabilities/xss_r/?name=<script>alert(Serendipity)</script>     

如果payloda改成下面这个:

       http://www.dvwa.com/vulnerabilities/xss_r/?name=<script>alert(document.cookie)</script>     

便能实现获取当前用户的cookie,这种攻击结合csrf(跨站请求伪造),例如通过 XMLHttpRequest与CORS功能将数据发送给攻击方服务器,之后便可以在千里之外模拟用户登录,进而进行恶意操作。

这类攻击也有很多防御手段,其中一种便是利用str_replace将<script>删除,但上有政策下有对策,这类方法可以使用使用双写绕过:

       http://www.dvwa.com/vulnerabilities/xss_r/?name=<scr<script>ipt>alert(document.cookie)</script>     

写到这里,忽然想到了一个很有趣的故事,之前 @lokinko 对我说:为了防止抄袭,自己会将网名lokinko随机插入到文章中,我当时随口说了句,建议将标识符改为loklokinkoinko,就是用的这个梗,也不知道他有没有get到呢?

更高级别的代码可能会使用preg_replace函数来过滤删除所有关于<script>标签,但使用<IMG src=1 onerror=alert(document.cookie)>也可以得到同样的结果。

攻击和防御都在不断地升级进化,我这里就简单写点,不再长篇大论了。

存储型

存储型XSS攻击,是指将恶意代码被当做正常数据插入到服务器上的数据库中,当用户正常访问页面的时候,恶意代码从数据库中提取出来并被触发。

这类方法和反射型最大的区别在于其攻击载荷的存储位置不同,反射型XSS的攻击载荷并不存储在服务器上,攻击时需要将链接发送给特定用户,存储型XSS的攻击载荷直接保存在了服务器上,因此很多时候是无差别攻击。

例如一个留言板被黑客利用进行XSS攻击,提交了形如<script>alert(“please follow serendipity!”)</script>的代码,那么所有访问这个留言板的用户都将可能执行这段恶意脚本。

利用存储型XSS可实现劫持访问,盗取访问者cookie或者配合csrf攻击完成恶意请求等攻击。

DOM based XSS

DOM based XSS通过恶意脚本修改页面的DOM节点来发起攻击,是发生在前端的攻击。DOM型XSS的特殊之处在于,用户的输入经过了DOM操作,特别是在innerHTML、ajax中经常出现。

一般的攻击流程大致如下:

  • 攻击者构造出特殊的URL,其中包含恶意代码,例如<script>alert(document.cookie)</script>
  • 用户打开带有恶意代码的URL
  • 用户浏览器接受到响应后执行解析,前端JavaScript取出URL中的恶意代码并执行
  • 恶意代码窃取用户数据并发送到攻击者的网站,冒充用户行为,调用目标网站接口执行攻击者指定的操作。

可以看到,其和反射型XSS的介绍,很是相似。

小感想

XSS的有趣之处,在于其过多的绕过方式,例如介绍给lokin妹妹的双写绕过等。其次,类似于知乎这类夹杂着图片、文字、视频,甚至可能有自定义的样式和html提交的富文本,此类XSS非常难以防御,并不是一个过滤就可以解决的问题。

另外,也要考虑到实际业务场景的问题,别影响了知乎er的体验(并没有)。

现在,前后端的分离,安全框架的使用,使得大量的XSS攻击消声觅迹,但是老业务里仍然还是少不了这类不安全内容的,不信,看看铁路系统的flash吧(ε=ε=ε=┏(゜ロ゜;)┛

以上,谢谢~

类似的话题

  • 回答
    好的,我们来聊聊这三种大家可能有点混淆的 XSS 攻击方式:DOMbased XSS、存储型 XSS 和反射型 XSS。虽然它们都属于跨站脚本攻击(CrossSite Scripting,简称 XSS),但它们在攻击原理、发生位置以及恶意脚本的“落脚点”上,有着显著的区别。咱们就一点一点地剖析,争取.............
  • 回答
    这件事挺有意思的,网上关于“操作真实 DOM 慢”的说法深入人心,但你遇到的测试结果却指向了相反的方向,这背后其实涉及几个关键点,咱们一点点掰开了聊。首先,我们要明白,网上的“操作真实 DOM 慢”这个说法,大多数时候是在一个特定的语境下成立的,也就是频繁且无序地直接操作真实 DOM。想象一下,如果.............
  • 回答
    嫦娥二号全月七米分辨率DOM数据:深度解析与应用探索嫦娥二号任务,作为中国探月工程的又一辉煌篇章,不仅在月球探测领域取得了举世瞩目的成就,更留下了宝贵的数据财富。其中,全月七米分辨率数字正射影像图(DOM)数据,以其精细的地形细节和广泛的覆盖范围,为我们理解月球表面地貌、研究月球演化提供了前所未有的.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有