1、首要规则:不要使用无法信赖的模板
使用 Vue 时最基本的安全规则就是不要将无法信赖的内容作为组件模板。使用无法信赖的模板相当于允许任意的 JavaScript 在应用中执行。更糟糕的是,如果在服务端渲染时执行了这些代码,可能会导致服务器被攻击。举例来说:
js
Vue.createApp({
template: `<div>` + userProvidedString + `</div>` // 永远不要这样做!
}).mount('#app')
Vue 模板会被编译成 JavaScript,而模板内的表达式将作为渲染过程的一部分被执行。尽管这些表达式在特定的渲染环境中执行,但由于全局执行环境的复杂性,Vue 作为一个开发框架,要在性能开销合理的前提下完全避免潜在的恶意代码执行是不现实的。避免这类问题最直接的方法是确保你的 Vue 模板始终是可信的,并且完全由你控制。
2、Vue 自身的安全机制
1. HTML内容
无论是使用模板还是渲染函数,内容都是自动转义的,为了防止脚本注入。这种转义是使用 textContent
这样的浏览器原生 API 完成的,所以只有当浏览器本身存在漏洞时,才会存在漏洞。
2. Attribute 绑定
动态 attribute 的绑定也会被自动转义,从而防止在 title
attribute 解析时,注入任意的 HTML。这种转义是使用 setAttribute
这样的浏览器原生 API 完成的,所以只有当浏览器本身存在漏洞时,才会存在漏洞。
关于浏览器安全可看:juejin.cn/post/712530...
3、潜在危险
未经无害化处理的、用户提供的内容都有潜在的安全隐患,因此这应尽可能避免。
1. 注入 HTML
Vue 会自动转义 HTML 内容,防止意外地将可执行的 HTML 注入到应用中
用户提供的 HTML 永远不能被认为是 100% 安全的,除非它在 iframe 这样的沙盒环境中,或者该 HTML 只会被该用户看到。此外,允许用户编写自己的 Vue 模板也会带来类似的危险
2. URL 注入
ini
<a :href="userProvidedUrl">
click me
</a>
如果这个 URL 允许通过 javascript:
执行 JavaScript,即没有进行无害化处理,那么就会有一些潜在的安全问题。
如果你发现你需要在前端做 URL 无害化处理,那你的应用已经存在一个更严重的安全问题了。任何用户提供的 URL 在被保存到数据库之前都应该先在后端做无害化处理。
3. 样式注入
ini
<a
:href="sanitizedUrl"
:style="userProvidedStyles"
>
click me
</a>
假设 sanitizedUrl
已进行无害化处理,它是一个正常 URL 而非 JavaScript。然而,由于 userProvidedStyles
的存在,恶意用户仍然能利用 CSS 进行"点击劫持",例如,可以在"登录"按钮上方覆盖一个透明的链接。如果用户控制的页面 https://user-controlled-website.com/
专门仿造了你应用的登录页,那么他们就有可能捕获用户的真实登录信息。
你可以想象,如果允许在 <style>
元素中插入用户提供的内容,会造成更大的漏洞,因为这使得用户能控制整个页面的样式。
为了避免用户的点击被劫持,我们建议仅在沙盒环境的 iframe 中允许用户控制 CSS。或者,当用户控制样式绑定时,我们建议使用其对象值形式并仅允许用户提供能够安全控制的、特定的属性,就像这样:
ini
<a
:href="sanitizedUrl"
:style="{
color: userProvidedColor,
background: userProvidedBackground
}"
>
click me
</a>
4. JavaScript 注入
强烈建议任何时候都不要在 Vue 中渲染 <script>
,因为模板和渲染函数不应有其他副作用。绑定任何用户提供的 JavaScript 给这些事件 attribute 都具有潜在风险,因此需要避免这么做。
没有切实可行的方法,能够在以下两种场景中保护开发者不受 XSS 的影响。
- 开发者显式地将用户提供的、未经无害化处理的内容作为 Vue 模板渲染。这本身就是不安全的,Vue 也无从溯源。
- 开发者将 Vue 挂载到可能包含服务端渲染或用户提供内容的 HTML 页面上,攻击者提供的 HTML 可能在普通 HTML 中是安全的,但在 Vue 模板中是不安全的,这就会导致漏洞。最佳实践是:不要将 Vue 挂载到可能包含服务端渲染或用户提供内容的 DOM 节点上。
4、后端协调
类似跨站请求伪造 (CSRF/XSRF) 和跨站脚本引入 (XSSI) 这样的 HTTP 安全漏洞,主要由后端负责处理,应该与后端团队保持沟通,了解如何更好地与后端 API 进行交互,例如,在提交表单时附带 CSRF 令牌。