Instagram Stored OAuth XSS

2:27 PM

A few weeks ago, I found a stored cross site scripting bug in Instagram that was tricky to craft a real exploit from. In Instagram Developers, you can create your own OAuth applications to be granted by the user and use the API. the vulnerable parameter is the "url" POST parameter, where you provide your site's address and the user could navigate to see the developer.

The parameter was properly sanitized, & even sent to Linkshim to validate its not a malicious link. but here is the best part: Linkshim only validates if the link is malicious from a list of database files it have and if it doesn't exist in the db, it will just put the url in a hyperlink reference.

And because of this Facebook assumed when a link is sent thru linkshim, a link would get out. and they are right, and they are validating everything right. except for the scheme.

So worked but since schemes weren't validated, so did javascript:// At this point, it will seem like we got a working exploit. but there are different limitation factors here. the first one being there are lots of character limitations to write a payload. because characters are properly HTML entitied, we can't use quotes & other key elements. and because linkshim is there, the payload needed to be a valid & safe-uri, but with our payload.

Crafting an alert was easy, we just put javascript://`Hello!`

The above payload can generate an alert that says "Hello" in any modern browser thanks to ECMAScript6. notice there aren't any braces or quotes in there, and I added a newline (%0A), to make the alert not a javascript comment because linkshim would require us to follow standard scheme protocols (xxx://y)

Going Beyond Alert

This part is just an extension to prove exploitability. because of Session cookies, this wont be as simple as stealing cookies then saying game over. also because of the limitation factors I wrote above, crafting a normal payload isn't an option.  

So I had to use DOM manipulation techniques to get the Authorization button when clicked, authorizing our malicious application to be used on behalf of the user with all the scopes available (comments+likes+basic+public_content+follower_list+relationships)

The pre-final payload I crafted looks like:  


As you can see we didn't use any quotes but only the allowed characters, and when visited, that will
authorize the malicious application in-to the users account. :) so the final payload would look something like:



Report Timeline

July 24, 2016 - Inital Report
July 26, 2016 - Triage
July 30, 2016 - Patch!