Sunday, March 1, 2015

Facebook: Another Linkshim Bypass


I wasn't going to post about this but it turns out, this could be an interesting article to post because this is the 3rd vulnerability that got fixed in the same parameter 6 months later.

You can find my inital linkshim bypass to this exact position which later turns out to be XSS if you click here. In the first bug I found in the continue parameter, it is possible to bypass linkshim and force a redirection to a site before being checked but then, XSS. later, this resulted some media attention and now when I find another linkshim bypass, I taught why no one else actually found this bypass, after the first got public. and that is one of the main reasons I am posting this.

I am going to talk about a relevant and great technique I learned from the prompt.ml XSS Challenge(s) 4, you can find the DOM XSS challenge here. consider the code:

function escape(input) {
    // make sure the script belongs to own site
    // sample script: http://prompt.ml/js/test.js
    if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {
        var script = document.createElement('script');
        script.src = input;
        return script.outerHTML;
    } else {
        return 'Invalid resource.';
    }
}

This is the JS source code of challenge 4. they basically want you to bypass a regex to get an external redirection. And the main problem here is that it uses decodeURIComponent(), a function that decodes supplied input from URL encoding. In this case, we can trick the browser believe the prompt.ml domain (allowed by the regex) belongs to our URL. This should be very simple using HTTP auth, like http://prompt.ml@attacker.com the above URL redirects to attacker.com and should bypass the regex because having the prompt.ml.

To bypass decodeURIComponent(), we simply have to use %2f which is a URL encoded representation for the /. And our bypass is: 
//prompt.ml%2f@.ws/

The trick to solve the level with 17 characters only lies hidden in a transformation behavior some browsers apply when converting Unicode characters to URLs. A certain range of characters resolves to three other characters of which one is a dot - the dot we need for the URL. The following vectors uses the domain 14.rs that can be expressed by two characters only.”

A url that starts with two forward slashes is treated as absolute by browsers.
Something similar seems to cause this issue (server-side), when given the continue parameter,

This successfully will send example.com for a check to a linkshim before extermal redirection which means https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=http://evilzone.org should be malicious.

Now a stupid enough URL validator will consider //evilzone.org a relative location and won’t allow us create a hyperlink like <a href=”//evilzone.org”> and Facebook obviously have black listed //

The next try should be \/evilzone.org, since most browsers render \ back to / this usually bypass the check and create //evilzone.org (you can read more about this from @homrkov’s Evolution of Open Redirection post)

So // and \/ got caught. At this point I concluded the linkshim uses number of blacklist based checks from \\, //, \/ and started fuzzing.

Thanks to @FransRosen, he told me about a technique that could create this bypass. \%09/@site.com
This basically should be equivalent to //@site.com and since the regex won’t find \%09/ , \%0D/ or \%0A/ blacklisted, this will result // because the %09 should obviously get ignored while parsing. And the complete linkshim bypass will look something like:




Feb 1, 2015 6:33am - Inital Report
Feb 1, 2015 6:47am - More Clarification sent
Feb 2, 2015 6:11am - More Classfication asked 
Feb 3, 2015 1:04pm - Some more clarifications sent
Feb 4, 2015 11:25am - Escalation of bug    
Feb 23, 2015 11:00am - Bug Fixed
  
Thanks you for reading! :-)


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.