这些年,AngularJS、React 和 Vue.js 算是前端框架中比较热门的,相对于 jQuery 等框架,有一些不太一样的可能出现问题的点,当然都是集中在 XSS 上。
模板注入
类似后端模板注入,前端模板注入也是存在的,被分析最多的还是 AngularJS,详见 https://docs.angularjs.org/guide/security
首先是后端直接生成前端模板,比如 {{1+1}}
,然后 AngularJS 去解析和执行。
其次是前端部分表达式和表达式 parser 的参数可以被控制,比如 $watch(userContent, ...)
$compile(userContent)
之前的 AngularJS 是有沙箱的,隔离了部分 runtime context,但是最新版本中去除了,因为多次的被绕过,而且并没有真正的提升安全性。
在其他框架中也是存在类似的问题的,比如 Vue.js 这里有一个有趣的案例 https://inside.pixiv.blog/kobo/5962
直接插入 HTML
MVVM框架一般不需要关心 dom 操作,但是有时候还必须手动的插入和控制一些 HTML,框架也是提供了相关的方法的。
- Vue.js 的
{{{ data }}}
和v-html
- AngularJS 的
$sce.trustAsHtml
- React 的
dangerouslySetInnerHTML
这时候就应该认真检查用户输入的数据了。
我感觉 AngularJS 和 React 的函数名字设计的特别科学,你要知道 trust 那些 dangerous 的数据才可以,还比如 grpc 中,使用非 SSL 的时候,方法名是add_insecure_port
。
SSR
为了解决 SPA 页面的 SEO 问题的,主流框架也提供了 SSR 方案,但是 SSR 的时候就经常的忘记了转义和过滤,一个是说程序员的问题,使用了危险的函数,另外一个就是框架的漏洞了。
比如新版知乎页面使用了 SSR,会先把用户的问题输出到页面上,然后后续再执行 JS 做进一步的动作,然后估计是使用了dangerouslySetInnerHTML
,导致用户问题中的 JS 被执行,导致了XSS。
Vue.js 在 SSR 的时候,默认会转义用户输入,但是在样式中忘记处理了,导致了 XSS。见下面的 demo
var Vue = require('vue')
var app = new Vue({
data () {
return {
xss: '"><script>alert(1)</script>'
}
},
render: function (h) {
return h('a', {style: {color: this.xss}}, 'foo')
}
})
var renderer = require('vue-server-renderer').createRenderer()
renderer.renderToString(app, function (error, html) {
if (error) throw error
console.log(html)
})