# 什么是 XSS

Cross-Site Scripting(跨站脚本攻击)简称 XSS。本质是将恶意代码 / 脚本注入目标网站,从而读取用户的敏感信息(如 cookie,sessionId)危害数据安全。

# XSS 常见场景

例如,我们有时候需要从 URL 取参数在页面上展示。

1
2
3
4
5
6
7
8
9
<body>
用户搜索的关键词为:<p></p>
<script>
const params = new URLSearchParams(location.search);
const keyword = params.get('keyword');
const pDom = document.querySelector('p');
pDom.innerHTML = keyword;
</script>
</body>

如果这时访问的 URL 查询参数为: keyword=<img src="x" onerror="alert(1)">

网站会尝试从一个不存在的地方下载 img,然后触发 onerror 之后调用 alert(1) ,如果换成读取用户的 cookie 之类敏感消息,就会造成危险。

# XSS 分类

# 存储型 XSS

  • 攻击者把恶意代码提交到目标网站的数据库。
  • 服务端把恶意代码从数据库取出返回给客户端(如拼接 URL 参数)。
  • 客户端解析代码中的恶意代码并执行。
  • 恶意代码可能将用户的敏感信息取出并发送到自己的网站。

# 反射型 XSS

  • 攻击者构造出一个恶意 URL 诱导用户点击。
  • 打开 URL 后,服务器取出恶意代码并返回给客户端。
  • 客户端解析代码中的恶意代码并执行。
  • 恶意代码可能将用户的敏感信息取出并发送到自己的网站。

存储型 XSS 和反射型 XSS 的区别在于:前者是将恶意代码注入数据库,后者是存储在 URL 中。

# DOM 型 XSS

  • 攻击者构造出一个恶意 URL 诱导用户点击。
  • 打开 URL 后,前端 JS 读取 URL 参数中的恶意代码并执行。
  • 恶意代码可能将用户的敏感信息取出并发送到自己的网站。

DOM 型 XSS 和前两者的区别在于:其被攻击的过程由浏览器(前端 JS)完成,不涉及服务端。

# XSS 预防

我们可以从 XSS 攻击的两个要素来预防。

  1. 攻击者提交恶意代码。
  2. 浏览器执行恶意代码。

# 输入过滤 / 转义

比如前端对用户的输入内容进行 HTML 转义后再发送给服务端,是否可行?
答案是不可行。攻击者可以构造请求做到跳过前端的过滤。
那么换个角度,我们在服务端进行代码的转义,然后把安全的代码存储到数据库,之后做到将安全的代码返回给前端,是否可行?
这种做法有两种潜在的问题:

  1. 转义后的代码有可能被输出到浏览器前端 / JS 客户端执行。浏览器会对转义字符进行编码,而 JS 不会。
  2. 转义的代码如果拼接在 HTML 中可以编码后正常运行,但是如果返回后赋值给 JS 变量也无法编码。

# 小心的拼接 HTML

如果必须要有拼接 HTML 的操作,可以使用合适的转义库。或尽可能使用 .innerText.setAttribute() 之类的 API 进行赋值拼接,减少使用 .innerHTML 此类操作。

# Content Security Policy(CSP)

有时候注入的恶意脚本是某个外部 src 的 script 脚本,这时候我们可以配置 CSP 白名单来阻止未知来源的的 script 资源加载。
你可以在 HTTP 头或是 meta 标签进行配置。这里简单介绍一下 HTTP 头如何配置。

1
Content-Security-Policy: default-src 'self'

上面代码表示所有的资源都只能从当前域名加载。
还有常见的场景是对 script 脚本进行单独配置,例如 nonce 值来发送一个 token,当加载脚本时进行验证。

1
2
3
4
5
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>
// 可以执行
</script>

# 其他安全措施

  • HTTP-only:对 cookie 设置 HTTP-only 属性,防止在 XSS 攻击后直接读取 cookie。
  • 验证码:在进行操作时需要读取屏幕的验证码输入验证,辨别人类与机器。

参考文章:

美团 - 前端安全系列(一):如何防止 XSS 攻击?

阮一峰 - Content Security Policy 入门教程

更新于

请我喝[茶]~( ̄▽ ̄)~*

imtangx 微信支付

微信支付

imtangx 支付宝

支付宝

imtangx 贝宝

贝宝