Header-Bar

December 8, 2014

AliExpress DOM-Based XSS (Main Registration Page) And Reflected XSS in Alibaba WebATM Online chat



What is DOM-Based XSS?

"In order to understand DOM XSS, we need to describe a bit what DOM is, and why is it relevant to this context.
The Document Object Model is a convention for representing and working with objects in an HTML document (as well as in other document types). Basically all HTML documents have an associated DOM, consisting of objects representing the document properties from the point of view of the browser. Whenever a script is executed client-side, the browser provides the code with the DOM of the HTML page where the script runs, thus, offering access to various properties of the page and their values, populated by the browser from its perspective.
DOM XSS is a type of cross site scripting attack which relies on inappropriate handling, in the HTML page, of the data from its associated DOM. Among the objects in the DOM, there are several which the attacker can manipulate in order to generate the XSS condition, and the most popular, from this perspective, are the document.url, document.location and document.referrer objects."

Proof Of Concept


In this specific case, the XSS occur when user input is being rendered after being called by this Javascript code:


The vulnerable page is the main "Join Free" registration page:

http://us.ae.aliexpress.com/wsuser/buyerJoin/expressJoin.htm?return=http%3A%2F%2Fwww.aliexpress.com%2F

Adding the following parameter should populate the vulnerable field:
_fmw.e._0.e=[XSS]

Here's what happens on a regular input:


Once a user decided to input a supposedly email string, the following <input> tag is being called:

<input id="email-ipt" name="_fmw.e._0.e" value="" type="text" tabindex="1" autocomplete="off" maxlength="128" class="redborder">

The important part of that element is of course - its ID. Using the get() Javascript function we can get the input which was submitted to the following element.
In this case, the Javascript file will hold the following reference: get("email-ipt")

Next, the code will append a string from a short list of known email domains:

<div id="email-prompt" class="email-prompt" data-index="-1">
<ul>
<li data-domain="@gmail.com">XSS@gmail.com</li>
<li data-domain="@hotmail.com">XSS@hotmail.com</li>
<li data-domain="@yahoo.com">XSS@yahoo.com</li>
<li data-domain="@mail.ru">XSS@mail.ru</li>
<li data-domain="@aol.com">XSS@aol.com</li>
<li data-domain="@yandex.ru">XSS@yandex.ru</li>
</ul>
</div>


Notice how the list is being wrapped by an "email-prompt" div element which we should see later when we look into the Javascript file.

So now that we saw what the static code is up to, let's see the Javascript.
Since it's a pretty large Javascript file (600+ lines), I decided not to go through each chunk. Let's look at the incidents that we know that has something to do with our attack.

The first encounter is here: (line 375)

AE.Wholesale.Join.prototype = {
    init: function() {
        return this.bindEvent(), this.initTimer(), this.isIE89() && this.initPlaceholder(), get("email-ipt").focus(), this.clickStat("new_regsiter_landing"), this.checkErrorType(), this
    }

focus() means "whenever a user clicks the field". This code is being called and returns 7 values into AE.Wholesale.Join.prototype. The 4th is our subject, once clicked.

And here is our interesting snippet:

YUE.on(get("email-ipt"), "keyup", function(t) {
       if (this.value.indexOf("@") >= 0) {
       e.showEmailPrompt(this.value);
       var n = get("email-prompt").getElementsByTagName("li"),
       r = [];
       ...
       ...
       ...
            } else e.hideEmailPrompt()


So email-ipt is our input and email-prompt is the actual action that prints our input to the screen, as we saw on the image above ("aaa@...").

if (this.value.indexOf("@") >= 0)

This says that only if a '@' character is located in the focus, please prompt the content list, else - e.hideEmailPrompt() Which hides the dropdown list.

Great! We are in the right location. Now let's dive and see if that's the code that executes our XSS.

e.showEmailPrompt(this.value);

This function takes the user input from its start until it bumps a '@' symbol. Than it looks for a static list of <li> elements with the data-domain attributes and embed the user input into it.
In any phase of the script, no validation on the user input is being taken.

Here is the showEmailPrompt()

showEmailPrompt: function(e) {
        var t = e.indexOf("@"),
            n = e.substr(t),
            r = e.substring(0, t),
            i = get("email-prompt").getElementsByTagName("li"),
            s = 0;
        for (var o = 0; o < i.length; o++) {
            var u = i[o].getAttribute("data-domain");
            u.indexOf(n) >= 0 ? (YUD.removeClass(i[o], "hide"), i[o].innerHTML = r + u, s++) : YUD.addClass(i[o], "hide")
        }
        s === 0 ? YUD.addClass(get("email-prompt"), "hide") : YUD.removeClass(get("email-prompt"), "hide")

    }

Now we can assume that injecting a Javascript code should reflect back, utilizing this domain object to generate the XSS prompt.

The following video illustrates how this could be accomplished:



Hope you enjoyed.

References:

https://www.owasp.org/index.php/DOM_Based_XSS
http://www.acunetix.com/blog/articles/dom-xss-explained/


This issue was reported to AliExpress.

TimeLine:
Reported on Dec 8th 2014.
Dec 10th, 2014: Alibaba security received the issue:
"Dear Naor.

         We have received your report, thanks!

Engineers are checking and fixing .and we will feedback in 24 hours.

We will follow the "Vulnerability Rewards Program", give a reward to you!

Thanks.


Another Reflected XSS was found and fixed a couple of days later. Very straight forward. This one is in the online chat feature called WebATM.



No comments:

Post a Comment