TOC:
![5e3da2b653e25876748160206d247394.png](https://img-blog.csdnimg.cn/img_convert/5e3da2b653e25876748160206d247394.png)
约定
- 本文中出现由花括号包裹的内容为服务端进行 html 字符串拼接的动态内容:{ userData },在其他文章中经常表现为 <%= userData >。
- 本文中所使用的关键词:“用户数据”,与“非受信数据”同义。
XSS 简介
XSS 是一种代码注入攻击,在受害者浏览器上注入恶意代码并执行,本质是前后端渲染不受信任的用户数据导致的安全问题。
不受信任的用户数据指的是由用户提供的数据,例如:用户在表单中输入的值,用户在 URL 中拼接的字符串等等。通常表现为恶意的 JavaScript 脚本或 CSS 脚本。
XSS 种类
通常我们把 XSS 分为三大类:存储型、反射型 以及 DOM 型。
存储型和反射型是服务单渲染(SSR)所导致的安全问题。
而 DOM 型则是客户端渲染(CSR)所导致的安全问题。
存储型【Stored XSS (AKA Persistent or Type I)】
1、顾名思义,攻击者提交的恶意数据被存储在目标站点的服务器(如数据库中)
2、受害者访问目标站点,服务端没有安全的处理用于拼接 HTML 的数据,并将有问题的 HTML 发送给浏览器
3、恶意代码在受害者浏览器中执行,受到攻击
反射型【Reflected XSS (AKA Non-Persistent or Type II)】
1、反射型与存储的区别在于,反射型是非持久性的,大多是同构 URL 的参数进行恶意代码的注入
2、受害者点击由攻击者预先设计好的恶意 URL,跳转到目标站点
3、目标站点从 URL 中取出恶意数据并拼接 HTML,再发送给浏览器
4、恶意代码在受害者浏览器中执行,受到攻击
DOM 型【DOM Based XSS (AKA Type-0)】
第一个提出 DOM 型 XSS 攻击的是 Amit Klein,DOM 型不需要服务端参与,是纯前端安全问题。从恶意数据源 到 接受并处理恶意数据的接收器都在浏览器中。
其中恶意数据源包括不限于:URL(如:document.loaction.href),HTML 元素等。
处理恶意数据的接收器如 document.write()、innerHTML、setTimeout/setInterval、eval 等等。
小结
1、如果你的项目是服务端渲染,又因为服务端渲染的内容几乎不会是纯静态的,因此我们需要注意存储型、反射型以及DOM型攻击,这些都有可能发生。
2、如果你的项目时客户端渲染,那么只需要注意 DOM 型攻击即可。
XSS 的危害
用户提供的数据,我们应该始终作为不受信任的数据处理,一旦把不受信任的数据在浏览器中执行,例如一段 JavaScript 脚本,那么该脚本将拥有完全的控制能力,它可以盗取用户私密信息,例如 cookie 等,可以改变站点的样式从而诱导“点击劫持”,这段恶意脚本可以代表用户执行任何操作。
存储型和反射型 XSS 的防御
防御 XSS 攻击没有想象的容易,但也没有想象的那么难,存储型和反射型需要服务端参与,我们接下来就讨论一下如何防御这类攻击,并给出 Vue SSR 的情况下是否会有某些问题,当然接下来介绍的某些攻击手段不仅仅会存在于 SSR 中,在 CSR 中也是有问题的,我们都会提及。
首先我们要明确一件事儿,任何安全问题都是在错误的信任用户提供的数据所导致的,因此,任何用户提供的数据都应该被特殊对待,在必要的情况下做正确的处理并展示。
1、插入到 html 标签内的用户数据
案例:
<div>{ userData }</div>
如果 userData 的内容是 '<script>alert(document.cookie)</script>'。那么最终拼接而成的字符串将是:
<div><script>alert(document.cookie)</script></div>
很显然,浏览器会弹出窗口,并展示 cookie。
防御方式:
在将 userData 展示给用户之前,要对其进行 html 转义(escape),既将如下字符转移成对应的 html 实体:
- & → &
- < → <
- > → >
- " → "
- ' → '
- / → /
这样,转义后的 html 将变成:
<div><script>alert(document.cookie)</script></div>
Vue 的 SSR 或 CSR 是否存在这个问题?
无论是 SSR 还是 CSR,如果是用模板插值,即 { {}},是不存在问题的,Vue 会对数据做 html 转义,但如果使用 v-html 指令,则会存在此问题。
2、作为普通标签属性值的用户数据
这里的普通标签属性,指的是非 href/src/style 以及事件属性(例如 onlick 等)之外的其他属性。
案例:
<div value={
userData }></div>
如果 userData 的内容为: