Facebook's Moves - OAuth XSS

10:33 AM

Its been a while since I have blogged. I have since became a twitter person. mostly reading peoples findings.

Anyway, this is going to be a short post about causing an XSS on Moves. As many of you might know, Moves (moves-app) is a part of Facebook's Bug Bounty program.


OAuth - for those of you who dont know, is an open standard for authorization. OAuth provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials.

Many big sites like Facebook, Google, Twitter and Dropbox use it to share specific access from a user to third-parties.
In http://dev.moves-app.com/ developers can create their Moves application(s) by using OAuth 2.0. meaning, by simply creating an application with redirect_uri, the thirdparty can get access to Moves profiles with the provided scope (location, access, read/write...).

The part that caused the XSS is the redirect_uri, they have blacklisted certain schemes from being added. forexample, I can't add "javascript://", "data:" and other protocols to the redirection url for the application I am creating.

If you notice carefully, those aren't the only dangerous schemes when it comes to script execution. for example, using "vbscript://" was possible. but due to the unlikely conditions that the user have to use an older version of Internet Explorer to get that executed, that was almost a dead end.

Bypassing Filter

As you might know, blacklisting may not be the right solution when it comes to XSS.

Things we know,:
it will expect either http or http(s)
schemes need to contain protocols. (://)

using dAta:// and jAvaScRipT:// worked with http(s?):// following them. because the regex wasn't checking for case sensitivity/i.

so redirect_uri=jaVaScrIpt://alert(0);//http:// is an ideal payload. because http will be treated as a comment.

However, there are no known payloads that will execute a script after using the data:// scheme like that, an ideal payload would be something like data:text/html;<script>alert(0)</script> but that wasn't possible.

Next is javascript, using javascript://alert(0) is also not an option, considering javascript will treat parts following it as a comment. turns out we can use newlines and breaks to cause script execution. so javascript://%0Aalert(0)//http:// works fine and causes that alert() we all love to see.

<a href="javascript://%0Aalert(0)//http://">Click</a>

works fine. but only in the <a>nchor context. but not in the redirection.
so Location: javascript:anything() actually doesn't work (just became aware of this because @filedescriptor mentioned it, I had no clue)

However, data:// schemes work fine. so data:// is our ideal payload. but turns out the :// isn't actually mandatory, because the http:// following in the comments can help within.

Ideal solution: daTa:text/html:base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K#http://

Errors. Errors eveywhere. Solution: URL encoding.

Simply by encoding the URL it is possible to get a working payload,

Final solution: daTa:text/html%3Bbase64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K%23

PoC: https://api.moves-app.com/oauth/v1/authorize?response_type=code&client_id=2KQ3D5coba76A5eg42mlu3L3Kd3btEeS&scope=location&redirect_uri=daTa:text/html%3Bbase64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K%23http://


UPDATE: Abdellah mentioned this can be exploited automatically using a well known OAuth misconfig. simply changing the "scope" to unknown, an error will be triggered that will force an error redirection to the redirect_uri (which in this case is the malicious paylaod). so this should work fine:
or, moves will exploit its ownself for us, with no user-interaction whatsoever. here is the secrete:

If no user-interaction is occured, moves will redirect to the redirect_uri in 9 seconds. and we simply set our malicious script as a redirect_uri and send that user to that page, even if he doesn't do anything, the exploit will trigger it self in 9 seconds. awesome!

simply by embedding the authorization url in an iframe or img tag, any moves user should be exploitable. here is a video demonstrating it:



24 November 2015 - Initial Discovery
2 December 2015 - Report
8 December 2015 - More data sent.
9 December 2015 - Escalated by Facebook
10 December 2015- Patch
10 December 2015 - Fix Confirmation

You Might Also Like