为什么Flash还荼毒人间?
Flash依然是一个威胁。在2017年,我报导了Facebook,Youtube,WordPress,Yahoo,Paypal和Stripe上的Flash漏洞,在过去的三年里,我有报告了超过50个赏金程序bug的flash漏洞,赚了80K+的奖金。而且还有更多的我没有报告,或者我报了也没有修复。
另外,Flash已经被新的javascript/html5特性所取代。这些特性增加了复杂度和新的类型的漏洞,比如不好的CROS实现,由postMessage或者XHR
Request,引起的DOM Xsses。了解Flash的失误可以帮助设计实施更加安全的javascript程序。这个新的Youtube
html5的Api很可能是从Youtube的Flash
Api移植到lavascript上的,使得它学起来更有趣。实际上,我通过所掌握的Flash
Api的知识就能找到Youtube的html5的xsses。
我会解释我在Youtube的Flash Api中发现的一些高级的Flash漏洞,并且在这个过程中和Html/javascript做一个对比。这个太专业了,所以有槽尽管吐。如果有人不太明白或者想增长新知识。你可以看一下这里的Flash安全模型。
逆向工程Youtube的Flash Api
Youtube Flash Api允许开发者在外部网站嵌入youtube的视频。
这是APi流程图:
这个入口函数,Youtube是一个位于youtube.com/v/[Video_ID]的一个Flash文件,这只是HTML页面和主App的一层包装。主App是一个大约100k的一个大Flash文件,被放置在域名为s.ytimg.com的沙盒内。
这些模块处理类似于副标题或者广告之类的可选函数。他们不能是单独的Flash文件,必须得被主App加载才行。
另外,还有一个Flash到JavaScript的Api,允许html页面给youtube api发送诸如play(),pause()之类的命令。Flash文件也会执行ajax风格的跨域请求,加载配置文件和视频内容。
用户信息泄露
从一个简单的漏洞开始讲起吧,这有一个在Flash ActionScript3中的简化版的Youtube封装器代码。
public class YoutubeWrapper extends Sprite{
private var user_name = "The Victim";
private var user_picture = "https://googleusercontent.com/.../victim_photo.jpg";
private var appLoader = new Loader();
public function YoutubeWrapper(){
// allow external javascript/Flash files to access its public properties
Security.allowDomain("*");
// load the Main App
this.appLoader .load(new URLRequest("https://s.ytimg.com/.../watch_as3.swf");
// add as child of display container
this.addChild(this.appLoader );
// loaderInfo.sharedEvents Api
this.loader.contentLoaderInfo.sharedEvents
.addEventListener("REQUEST_USERINFO", this.onRequestUserinfo);
}
private function onRequestUserinfo(event:Event){
// write the user info into the event.data property
// which is accessible to the sharedEvents caller
event.data.user_name = this.user_name;
event.data.user_image = this.user_image;
}
}
youtube封装器立即生成,它的属性“User_name”包含了google用户的名字(如果他是连接到google的)这个属性"user_picture"包含了用户轮廓图的链接。在这个bug中,攻击者会窃取这些数值。
youtube封装器能从开发者自己的Flash文件中加载(还是叫它恶意封装器)这种情况下,它们都能在一个不同的Flash保密的沙盒中执行。
加载一个外部的flash文件跟Html中加载\很相似。如果这个iframe来自于一个跟它的父类不同的源,他们因为Same-Origin Policy (SOP)原则就不能访问到彼此的属性。Youtube封装器包含了这段代码Security.allowDomain(“*”)来允许JavaScript给Flashapp发送play(),Pause()等命令。这还意味着恶意封装器可以获取到任何公开的属性,就好像它也在同一个沙盒里一样。然而,它是访问不到私有属性的。
user_name这个属性提供了loaderInfo.sharedEvents用于加载器和一个已加载文件之间通信。当这个主app分发一个时间给这个sharedEvents接口。这个youtube封装器接收这个事件并使用event.data属性把用户信息发送回去。
这跟javascript的postMessageapi允许跨域ifames通讯一样的道理。postMessage的api不仅可以被iframes和他的父类使用,还可以给其他链接到iframe和父类的window使用。任何任意域都可以通过window.open和window.frames获取这些链接,也不受被SOP限制。
如果恶意加载器能获取到这个特别的loaderInfo对象,就能给YouTube封装器发送一个事件并窃取用户信息。
loaderInfo是一个appLoader的属性,它是youtube封装器的一个私有属性,所以恶意封装器不能获取到。
然而,使用加载器时,如果你想显示这个加载的文件,你得把它当做显示容器的一个子对象。通常可以通过this.addChild(this.loader)方法来加入;实际上youtube就是这么做的。
问题在于,youtube封装器还有一个内建的公有方法getChildAt(),返回这个youtube封装器的孩子对象,这意味着,恶意封装器可以调用
把一个属性设置成“私有”被称为封装,然而,只有这个引用是私有的,而不是这个引用指向的对象。从这儿,恶意封装器可以获取到YoutubeWrapper.getChildAt(0).loaderInfo.sharedEvents,它是youtube封装器和主app之间的接口。恶意程序可以发送事件给youtube封装器,这个youtube封装器会在event.data里提供用户的信息,恶意的封装器也能读到这个event.data的值。
概念验证
POC工作流:
var loader = new Loader();
// Load the Youtube Wrapper
loader.load(new URLRequest("https://www.youtube.com/v/[VIDEO_ID]"));
var youtubeWrapper = loader.content;
// Access the Youtube Wrapper appLoader object
var appLoader = youtubeWrapper.getChildAt(0);
// Access the loaderInfo.sharedEvents of appLoader
var LeakingSharedEvents = appLoader.contentLoaderInfo.sharedEvents;
// Prepare the event to send to Youtube Wrapper
var leakEvent = new Event("Request_username");
leakEvent.data = new Object();
// Send the leakEvent to the LeakingSharedEvents
LeakingSharedEvents.dispatchEvent(leakEvent);
// The username is now accessible in the event.data property
trace(leakEvent.data.user_name);
trace(leakEvent.data.user_picture);
攻击方案:
前提:受害人记录在Google上,并且有flase player播放器
(1)受害者访问这个攻击者的网站http://evil.com/evil.html,网站包含了一个flash对象http://evil.com/evil.swf。
(2)evil.swf加载Youtube封装器并检索用户的Google账号。
影响:
任何网站都能用这个知道用户的身份,如果他们是使用Google来连接的话。想象一下,你随便访问一个网站都会显示你的名字和你的照片是什么感觉。
减灾:
为了解决这个问题,YouTube封装器停止往event.data属性里面写用户信息,取而代之的,把他直接发给了主APP。这样的话,即使是恶意的封装器给YouTube封装器发送事件,它也不会收到这个用户信息,因为信息都发给主APP了。
时间线:
08/27/2015 – 报告给Google VRP
09/09/2015 – 问题修复,获得奖励
这是一个简单的bug,我希望能给你启发,理解这儿的这些基本的挑战。你可以看一下另一个bug,在part 2部分,我们在youtube里面可以执行任意的Flash代码。
本文由看雪论坛 daemond 编译,来源opensec@Enguerran Gillier 转载请注明来自看雪社区