🗒️XSS

Cross-Site Scripting,跨站脚本,简写为 XSS(为了区分 CSS)

XSS(跨站脚本)是一种安全漏洞,会让攻击者有机会向网站注入恶意的 script。当受害者触发其执行之后,攻击者可能会利用该漏洞来绕过同源策略等访问控制,进而冒充用户。

由于用户的浏览器没法检测恶意 script 是不是不可信的,因此就会授予恶意 script 访问站点的敏感信息(比如 cookie、session token)的权限,进而以被攻击者的身份进行操作,或是让恶意 script 重写 HTML 内容。

时至今日,“跨站脚本”这一术语已经有些“词不达意”了,它最初是一种用于跨站点破坏数据的攻击,但后续开始慢慢包括其它形式的数据注入攻击。恶意内容通常包括 JavaScript,有时也包括 HTML、Flash 或浏览器可以执行的任何其它代码。

XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。

1. XSS 攻击举例

基于 XSS 的攻击种类几乎是无限的,但它们通常包括:

  1. 隐私数据相关,如 cookie 和其它 session 信息

    • 向攻击者传输隐私数据

    • 伪装成受害者,访问 API 或登录 server(如果 server 没有做相应的防护)

  2. 将受害者重定向到攻击者控制的网页

  3. 以易受攻击的站点为幌子在用户的计算机上执行其它恶意操作。比如:

    • 能在一定限度内记录用户的键盘输入

    • XSS 蠕虫

    • 利用 XSS 漏洞扫描用户内网

场景很多,主要就是因为没有做好转义,进而导致的一系列问题。比如:

  1. url 里有个参数,<script>alert('xss');</script>,没转义就显示在页面上了,可能会:

    • 弹出个恶意的消息

    • 脚本中有外链脚本,获取用户信息、模拟用户请求等

  2. input 输入的内容没有转义,存到了数据库,在下次作为 response 返回时,可能会使用不当

    • 若是在页面上显示(也没转义),导致页面混乱、恶意内容

    • 若展示成了一个可以点击的恶意链接

  3. 对于值可以是 <url> 的,除了转义,还要检测其内容,禁止以 javascript: 开头的链接和其它非法 scheme 或者是只允许特定 scheme。比如:

    • HTML 元素的 href、src 等属性

    • CSS 中的属性值(新版本浏览器已经可以防范)

2. XSS 攻击类型

主流的认为,至少区分两种主要类型的:非持久性(反射型)和持久性(存储型)。还有些资料会将这两组进一步分为传统的(由服务器端代码缺陷引起)和基于 DOM 的(在客户端代码中)。

  1. 反射型,也称非持久型,Reflected XSS Attack。常见于通过 URL 传递参数的功能

    • 大约就是没有做好转义,导致异常 script 执行或显示

    • 当用户被诱骗点击恶意链接、提交特制表单、浏览恶意网站时,注入的代码就会传输到易受攻击的网站。web 服务器将注入的脚本反射回用户的浏览器,比如在错误消息、搜索结果等任意的 response 中。浏览器执行代码是因为它假设 response 来自用户已经与之交互的可信服务器。

  2. 存储型,也称持久型,Stored XSS Attack。注入的 script 被永久地存储在了目标服务器上。当浏览器发送请求来获取 data 时,受害者就会从服务器那里拿到该恶意 script。

  3. 基于 DOM,DOM-based XSS Attack。通常和 server 的解析和 response 没直接关系,是在 script 动态执行的过程中产生的。

3. XSS 攻击预防

攻击的场景非常多,但是解决办法很集中,就是做好转义、管理好 cookie。

3.1 内容过滤

  1. 转义或编码:读的时候转义(url参数、input)、显示的时候转义(根据上下文 HTML/CSS/JS)

    • HTML 实体编码、JavaScript 转义、CSS 转义、URL 编码

    • 安全编码库

  2. 允许用户输入HTML的情况,就必须做一层 HTML 清理了。还挺复杂,要考虑的情况很多(大约就相当于一个 HTML 解析器了)

  • HttpOnly。虽然该功能很有用,但它既不能完全防止 cookie 被盗,也不能防止浏览器内的攻击

  • SameSite=Strict

3.3 业务逻辑

完善和优化业务逻辑,比如:

  1. Web 服务器:

    • 检测到同时登录并使会话无效

    • 检测到来自两个不同 IP 地址的同时登录并使会话无效

    • 设置为重定向无效请求

  2. 网站:

    • 只能显示以前使用过的信用卡的最后几位数字

    • 可能会要求用户在更改注册信息之前再次输入密码

3.4 脚本相关

  1. 禁用脚本:适用于某些无需任何客户端脚本的 web 应用程序

    • 某些浏览器或浏览器插件,可以按 domain 配置

    • 默认情况下阻止所有脚本和外部包含,然后允许用户在每个域的基础上启用它的功能更加有效

    • 浏览器:设置所谓的“安全区域”、使用其“站点特定首选项”

  2. 有选择地禁用脚本

    • CSP(Content Security Policy,内容安全策略)

      • 允许 HTML 文档选择禁用某些脚本,同时启用其他脚本。(似乎没啥效果)

      • 某项研究表明“总的来说,我们发现 94.68% 的尝试限制脚本执行的策略是无效的,并且 99.34% 的具有 CSP 的主机使用的策略对 XSS 没有任何好处。”

    • 随机数:现代 CSP 策略允许使用随机数将 HTML 文档中的脚本标记为可以安全运行,而不是将策略与页面内容完全分开。只要可信随机数仅出现在可信脚本上,浏览器就不会运行来自不受信任作者的程序

3.5 其它

客户端框架的流行改变了攻击者制造 XSS 的方式。

4. 主要参考

扩展阅读:

Last updated