QQ空间某功能缺陷导致日志存储型XSS

漏洞概要

缺陷编号:WooYun-2013-020186

漏洞标题:QQ空间某功能缺陷导致日志存储型XSS

相关厂商:腾讯

漏洞作者:gainover

提交时间:2013-03-16 23:11

公开时间:2013-04-30 23:12

漏洞类型:XSS 跨站脚本攻击

危害等级:高

自评Rank:15

漏洞状态:厂商已经确认

Tags标签:

漏洞详情

披露状态:

2013-03-16: 细节已通知厂商并且等待厂商处理中
2013-03-18: 厂商已经确认,细节仅向厂商公开
2013-03-28: 细节向核心白帽子及相关领域专家公开
2013-04-07: 细节向普通白帽子公开
2013-04-17: 细节向实习白帽子公开
2013-04-30: 细节向公众公开

简要描述:

QQ空间日志某处功能缺陷,导致存储型XSS。每次想去瞄一下QQ空间的时候,总能随手发现存储型XSS。关键代码定位+调试 小教学贴。

详细说明:

1. QQ空间日志里面有一个魔方日志的功能。我们随便写一篇模仿日志。2. 抓包,并且看发表日志后的内容。这里值得我们注意的是,HTML中输出的日志内容是一个 img标签,如下图

而我们看到的日志中,则存在FLASH。

3. 从上面可以推出,这里必然会经过某些dom操作,从而将IMG标签转变为OBJECT标签。我们先得到FLASH名称.

接着定位与这个魔方日志有关的功能代码。

-----------------------------分割线------------------5. 好吧,其实以上都是废话,重点是下面的,FLASH将我们带到了这个JS文件, 我们将 http://ctc.qzs.qq.com/qzone/app/blog/v6/script/content_gridsblog.js 美化一下,再看看代码。发现FLASH的部分并没有我们可控的部分。但是可以定位代码下面这样一段代码。GridsScheduler._showGridBlogShortcut();-->在 _showGridBlogShortcut 函数中,有eval('var oGridInfo = ' + PageScheduler.blogInfo.getGridData());6. PageScheduler.blogInfo.getGridData() 这个被eval的是什么数据呢?由于是iframe页面里的变量,直接控制台里没办法输出PageScheduler.blogInfo.getGridData, 我们可以采用“将网络JS映射至本地文件的方法”。

将映射到本地的JS文件里修改为

7. 接着我们刷新页面,重新打开日志。(* 由于_showGridBlogShortcut 函数中存在判断,必须以外人身份查看日志,才能触发。)看到弹出的 PageScheduler.blogInfo.getGridData() 数据如下。

8. 而这个数据,我们是否可控呢?答案是,我们很有可能可控,因为这个数据,我们提交日志的时候,就存在,如下图:

9. 既然如此,我们将 gridJson这个字段,修改一下,加一段自己的JS代码。

10. 以自己号码查看测试号码的日志,成功执行代码

ie,chrome下均可。

漏洞证明:

见详细说明

修复方案:

不影响功能的前提下,对eval的数据有所判断或者过滤。

漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2013-03-18 15:24

厂商回复:

非常感谢您的报告。这个问题我们已经确认,正在与业务部门进行沟通制定解决方案。如有任何新的进展我们将会及时同步。

最新状态:

暂无

评价

  1. 2010-01-01 00:00 鬼魅羊羔 白帽子 | Rank:274 漏洞数:36)

    一哥怒了。。

  2. 2010-01-01 00:00 小胖子 白帽子 | Rank:1429 漏洞数:107)

    第一个来马克,你是我心中永远的二哥,有些屌丝是无法超越你的,[email protected]

  3. 2010-01-01 00:00 小胖胖要减肥 白帽子 | Rank:492 漏洞数:66)

    @鬼魅羊羔 现在是三哥了

  4. 2010-01-01 00:00 鬼魅羊羔 白帽子 | Rank:274 漏洞数:36)

    @小胖胖要减肥 G博士永远都是俺们心目中的一哥。金枪不倒。。。

  5. 2010-01-01 00:00 xsser 白帽子 | Rank:152 漏洞数:17)

    切克闹,嘿喂狗,蠕动起来

  6. 2010-01-01 00:00 se55i0n 白帽子 | Rank:1483 漏洞数:156)

    @鬼魅羊羔 @小胖子 亲,我只是发个洞子嘛,,况且我是G牛的铁杆粉丝,,不多说啥子,,

  7. 2010-01-01 00:00 gainover 白帽子 | Rank:1331 漏洞数:97)

    请叫我九妹, 谢谢~

  8. 2010-01-01 00:00 猥琐 白帽子 | Rank:4 漏洞数:1)

    @gainover 九妹照片 http://photo.icxo.com/201011/20101141156.jpg

  9. 2010-01-01 00:00 小胖子 白帽子 | Rank:1429 漏洞数:107)

    @se55i0n 逗你玩儿呢,小气鬼~你永远是我的好基友~

  10. 2010-01-01 00:00 鬼魅羊羔 白帽子 | Rank:274 漏洞数:36)

    @猥琐 我擦,G哥亮了。。。

  11. 2010-01-01 00:00 冻心 白帽子 | Rank:5 漏洞数:3)

    切克闹,嘿喂狗,蠕动起来

  12. 2010-01-01 00:00 苏南同学 白帽子 | Rank:41 漏洞数:5)

    我们千寻不得,洞主手到擒来~ 赞~

  13. 2010-01-01 00:00 rasca1 白帽子 | Rank:39 漏洞数:8)

    我们千寻不得,洞主手到擒来~ 赞~

  14. 2010-01-01 00:00 陈再胜 白帽子 | Rank:101 漏洞数:13)

    看到教学贴,总要关注下····

  15. 2010-01-01 00:00 none 白帽子 Rank:40 漏洞数:5)

    二哥快要超越一哥了我只看精华)

  16. 2010-01-01 00:00 Defa 白帽子 | Rank:66 漏洞数:9)

    学费真贵,

  17. 2010-01-01 00:00 lucky 白帽子 | Rank:316 漏洞数:40)

    终于看见了!大作呀!学习

  18. 2010-01-01 00:00 th000 白帽子 | Rank:8 漏洞数:3)

    有意思

  19. 2010-01-01 00:00 lossite 白帽子 | Rank:20 漏洞数:2)

    @gainover 弱弱的问一句,为啥我必须加上属性才能执行,是不是我理解错了? eval('var x1='+ {"test":"(function(){alert(1)})()"}.test)

  20. 2010-01-01 00:00 gainover 白帽子 | Rank:1331 漏洞数:97)

    @lossite

    {"test":"(function(){alert(1)})()"}.test 的值实际上是字符串 "(function(){alert(1)})()", 与 'var x1=' 相加后,即为:

    var x1=(function(){alert(1)})()

    然后

    eval('var x1=(function(){alert(1)})() '); 执行代码。

    可能你想写的是下面的样子:

    eval('var x1={"test":(function(){alert(1)})()}');

  21. 2010-01-01 00:00 lossite 白帽子 | Rank:20 漏洞数:2)

    @gainover 多谢大牛,昨天测试的时候写成这个了,eval('var x1={"test":"(function(){alert(1)})()"}'); 多了两个引号。。。

  22. 2010-01-01 00:00 酷帥王子 白帽子 | Rank:94 漏洞数:12)

    尼玛看不懂呢,不过很精彩

  23. 2010-01-01 00:00 bitcoin 白帽子 | Rank:290 漏洞数:36)

    此人只因天上有

  24. 2010-01-01 00:00 乌帽子 白帽子 | Rank:28 漏洞数:2)

    怎么将网络js映射为本地的?