特性导致的安全问题之twitter bootstrap xss风险
余弦(@evilcos)
关于bootstrap
bootstrap是twitter开源的一个前端开发框架(http://twitter.github.com/bootstrap/index.html),你还在怕不会写HTML/CSS吗,各种布局样式超有Web2.0范,bootstrap都帮你搞定了,你只要会搭积木,就可以做出漂亮的网页:),bootstrap的js特效是基于jquery的,所以使用它之前还得调用jquery。
潜在XSS风险
我们在使用bootstrap发现了一个潜在的XSS点,这个最早是小虎同学(@not_so_bad)在做网页时发现的,弹出了一个框,吓了一跳,报给官方,被忽略。这个问题是这样的:
bootstrap的tooltips插件(http://twitter.github.com/bootstrap/javascript.html#tooltips)可以美化标签的title显示,我们知道默认的显示很一般的,就是操作系统UI的风格,美化后就亮了,不过亮是有代价的。看代码说话。
HTML里面如下代码:
1 |
<a id="x" href="#" rel="tooltip" title="<script>alert(document.cookie);</script>">hover over me</a> |
看,title里的值是我们特意htmlencode之后的结果,可是经过tooltips处理后,它会无论如何都进行htmldecode,解开了,然后html()输出后就执行了(157行):
1 |
$tip.find('.tooltip-inner').html(this.getTitle()) |
为何会htmldecode?那就继续跟进getTitle()函数进行分析:
1 2 3 4 5 6 7 8 9 10 11 12 |
getTitle: function () { var title , $e = this.$element , o = this.options title = $e.attr('data-original-title') // title值来自$e对象的data-original-title属性,这个属性在其它地方动态生成的,继续跟这个属性 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) title = title.toString().replace(/(^\s*|\s*$)/, "") return title } |
data-original-title属性来自这:
1 2 3 4 5 6 7 |
fixTitle: function () { var $e = this.$element if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') } } |
来自$e.attr('title'),动态赋值给data-original-title,这有啥奇怪的?到这其实就已经不是bootstrap的责任了,这是简单的jquery语句,得到对象的title属性的值。这个方式等效于:
1 |
document.getElementById('x').title; |
都到这了,那也不是jquery责任了……到底谁的责任??最后又回到了程序员身上,程序员也很无辜啊。不用你这个特性还好,用了,导致出现了XSS!那我想用咋办?得两次htmlencode,或者就清理掉任何有害的HTML标签,或者加个函数到tooltips插件中,让自动htmldecode的再encode回去……这样:
1 |
value.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g,'>') |
真折腾。无论如何,程序员们要注意这个特性,谨慎使用,使用不当就可能导致XSS攻击发生。
“特性导致的安全问题”系列,下一篇预告:python urllib2不恰当使用可能导致本地文件内容泄露:),请关注我们。
5条评论
bs的这个漏洞真的可以来XSS=。=
不过下一篇1l等了两年…
有个html的Options,这个应该能解决这个问题吧,还是说这个是新加的
htmlbooleanfalseInsert html into the tooltip. If false, jquery’s text method will be used to insert content into the dom. Use text if you’re worried about XSS attacks.
我感觉这个地方的问题是输出的问题,所以我觉得这样fix比较和谐.
$tip.find(‘.tooltip-inner’).text(this.getTitle())
对,我们提交的bug fix就是这个:)
坐等下一篇啊