0x01 SWFUpload简介

SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术为Web开发者提供了一个具有丰富功能继而超越传统标签的文件上传模式。

SWFUpload是在国内网站中使用得比较普遍的Flash插件。

0x02 Flash XSS

当SWFUpload的版本<= 时,会存在Flash XSS漏洞。

漏洞版本下载地址:https://github.com/JoyChou93/FlashXss/tree/master/swfupload

将文件下载下来后,反编译得到as源代码,可以看到脚本是有三个,这里先关注SWFUpload的代码:

SWFUpload的代码量略大,这里直接搜索外部参数输入的关键字,找到对应的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public function SWFUpload()
{
...
this.movieName = root.loaderInfo.parameters.movieName;
this.flashReady_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].flashReady";
this.fileDialogStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogStart";
this.fileQueued_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueued";
this.fileQueueError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueueError";
this.fileDialogComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogComplete";
this.uploadStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadStart";
this.uploadProgress_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadProgress";
this.uploadError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadError";
this.uploadSuccess_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadSuccess";
this.uploadComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadComplete";
this.debug_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].debug";
this.testExternalInterface_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].testExternalInterface";
this.cleanUp_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].cleanUp";
this.uploadURL = root.loaderInfo.parameters.uploadURL;
this.filePostName = root.loaderInfo.parameters.filePostName;
this.fileTypes = root.loaderInfo.parameters.fileTypes;
this.fileTypesDescription = root.loaderInfo.parameters.fileTypesDescription + " (" + this.fileTypes + ")";
this.loadPostParams(root.loaderInfo.parameters.params);

这里看到好几个变量都是外界可控的,有一个很特别,就是movieName变量,它会被拼接到很多名为xx_Callback的变量值中。我们就跟踪下第一个名为flashReady_Callback变量看看是不是可调用的:

1
2
3
4
5
if(ExternalCall.Bool(this.testExternalInterface_Callback))
{
ExternalCall.Simple(this.flashReady_Callback);
this.hasCalledFlashReady = true;
}

可以看到,在后面的代码中会作为ExternalCall.Simple()函数的唯一参数传入调用。

而ExternalCall.Simple()函数的定义是在另一个名为ExternalCall脚本中,我们到其中搜索看看:

bingo,是ExternalInterface.call()函数,且是第一个参数外部可控,妥妥的Flash XSS漏洞。

理下思路,存在AS3形式的loaderInfo.parameters来传入外部参数movieName,且存在ExternalInterface.call()函数的第一个参数外部可控,结合导致Flash XSS。

至于其他几个拼接的变量也是一样的分析。

这里结合ExternalInterface.call()函数的第一个参数的payload的形式,稍微修改下来闭合前面拼接的格式即可:

1
?movieName="])}catch(e){alert('mi1k7ea')};//

接着就是不停地弹框了:

在IE下调试,可以看到底层被恶意构造输入注入的执行的JS代码:

0x03 参考

Flash XSS检测脚本的简单实现