在 GitHub 上引用了一个哥们为 AngularJS 写的 markdown filter,在后台编辑的时候手痒试了下 XSS,果然弹出框了。
本来想直接在 GitHub 上换一套插件试试,结果研究了一下解决了这个问题。
AngularJS 中如果当前 module 引用了 ngSanitize,那么在页面中 ng-bind-html 默认是会进行 $sanitize 的过滤的,可以过滤掉 script 这种比较敏感的标签。
另外一种情况是,引用了 ngSanitize,但是在 controller 里面 $sce.trustAsHtml 函数返回,结果就是来什么执行什么,完全信任传入的 HTML 代码。
最安全的情况是不使用 ng-bind-html 而是使用 ng-bind,自动把符号都 HTML 编码了。但是显然 Markdown 从一开始就是拒绝的。
他的项目中 filter 是这么设计的,完全信任了 filter 获取到的 HTML 内容,导致 XSS 代码赤裸裸地被执行了。
.filter('markdown', ['$sce', 'markdown', function ($sce, markdown) { return function (text) { if(text == null) text = ''; var html = markdown.makeHtml(text); return $sce.trustAsHtml(html); }; }])
结果我改成,然后在 angular.module('markdown', ['ngSanitize']) 这里引入 ngSanitize,就可以让 AngularJS 自动的滤除 XSS 啦。
.filter('markdown', ['markdown', function (markdown) { return function (text) { if(text == null) text = ''; var html = markdown.makeHtml(text); return html; }; }])