5x3 精读Vue官方文档 - 安全

1,006 阅读2分钟

精读 Vue 官方文档系列 🎉

报告安全漏洞

如发现任何安全漏洞,请邮件给 security@vuejs.org。会有全职贡献者及时处理。

推荐始终使用最新版本的 Vue 及其官方的周边库,以确保应用尽可能安全。

永远不要使用不可信任的模板

永远不要将不可信任的内容作为模板内容使用,最典型的就是用户提供的内容,包括 HTML、JS、CSS。

HTML 注入

最典型的 XSS 攻击:

new Vue({
  el: '#app',
  template: `<div>` + userProvidedString + `</div>` // 永远不要这样做
})

Vue 内部会通过浏览器原生的 textContent 进行转义。 如果你完全能确保动态渲染的内容绝对正确,你也可以通过以下方式显示的渲染 HTML 内容:

  • 使用模板:
<div v-html="userProvidedHtml"></div>
  • 使用渲染函数:
h('div', {
  domProps: {
    innerHTML: this.userProvidedHtml
  }
})
  • 使用基于 JSX 的渲染函数:
<div domPropsInnerHTML={this.userProvidedHtml}></div>

Attribute 注入

通过闭合 Attribute 间接注入新的 Attribute 来实现攻击

var dynamicTitle = '" onclick="alert(\'hi\')';
var h1 = '<h1 title="'+ dynamicTitle +'">hello</h1>';

为了确保不会产生出此种攻击,我们应该总是基于 Vue 提供的 v-bind 指令来绑定 Attribute 并传值。

<h1 v-bind:title="userProvidedString">
  hello
</h1>

如果 userProvidedString 包含攻击代码,它会被转义为:

&quot; onclick=&quot;alert('hi')

该转义通过诸如 setAttribute 的浏览器原生的 API 完成,所以除非浏览器本身存在安全漏洞,否则不会存在安全漏洞。

将不安全的内容赋值给 onclickonfocusonmouseenter 等事件句柄

开发者应当时长保持风险意思,不要绕开 Vue 本身功能去操作模板。

URL 注入

主要是利用 href 属性可以执行 javascript:alert(\'hi\') 表达式的特性。

<a v-bind:href="userProvidedUrl">
  click me
</a>

最优的解决方案,是后端入库时就对 URL 进行过滤。

CSS 注入

<a
  v-bind:href="sanitizedUrl"
  v-bind:style="userProvidedStyles"
>
  click me
</a>

如果上例的 a 标签允许接收用户提供的不能 100% 保证安全的链接与样式,可以想象的到,攻击者会改变当前标签的展现样式。比如将其透明化并定位到登录按钮的上面,然后用户点击登录时,跳转到一个类似的钓鱼网站,从而窃取用户信息,进行“钓鱼攻击”。

解决方案就是不要给标签的 style 属性直接赋值,而是总是通过对象语法为特定的 CSS 属性赋值。

<a
  v-bind:href="sanitizedUrl"
  v-bind:style="{
    color: userProvidedColor,
    background: userProvidedBackground
  }"
>
  click me
</a>

通过沙箱来运行不安全的HTML、CSS、JS内容。

借鉴 CodePenJSFiddle 可以将不能确定是否安全的内容放置在一个 iframe 中以沙箱的方式来运行内容。

最佳实践

请详细阅读一下文章,它们详细的记录了各种攻击方法,从中吸取经验,加强我们应用的安全性: