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检测脚本的简单实现