Exploiting odd behaviors in MS Edge & IE to bypass Facebook’s Linkshim

2:32 PM


The following post is inspired by an all charset unicode shazz by @insertscript. After I saw it being referred in a tweet by Gareth Heyes, I immediately started fuzzing for more characters Internet Explorer & MS Edge may interpret horribly, and confuse the anchor host parser to ultimately use and bypass Facebook's Linkshim.

Fuzzing:

<a href=”/[$]example.com” id=”fuzzmeiah”>fuzz</a>
<script>

chars = [];
for(i=0;i<=0xffff;i++){
    if(document.getElementById('fuzzmeiah').hostname==example.com) {
      chars.push(i);
      console.log(chars.join('\n'))
     }
}

</script>

Result:


Character 1: 〱- 'VERTICAL KANA REPEAT MARK' (Ux3031)


The first one works for both IE & Edge is 0xE3 0x80 0xB1 (e380b1 aka 〱) , when plugged alone or after a forward slash, confusing the parsers to misinterpret the hostname.


<a href=”/〱example.com” id=”fuzzmeiah”>fuzz</a>


This can be tested in both MS Edge and Internet Explorer by changing links Facebook expects to be relative URIs and thus not passing them to a linkshim validation endpoint, allowing redirection to a blacklisted site (in this example, user must click on continue or cancel)




Character 2: 〵- 'VERTICAL KANA REPEAT MARK LOWERHALF' (Ux3035)




Character 3: ゝ- 'HIRAGANA ITERATION MARK' (0x309d)




Character 4: ー 'KATAKANA-HIRAGANA PROLONGED SOUND MARK' (0x30fc)



Character 5: ー 'HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK' (0xff70)




This specific issue is not fixed by Facebook as they believe it is more of the browser vendors fault and shouldn't be fixed from their side. Even though I disagree with their decision, I believe a very few percent of Facebook users use IE or Edge so I didn't bother trying to change their mind. I hope this post inspires either Microsoft or Facebook to fix this issue though.

I hope you enjoyed the read. =)

Why CSP Should be carefully crafted: Twitter XSS & CSP Bypass

3:09 AM


Few months back, I came across an oauth xss accompanied by a nice CSP bypass in Twitter. While creating an application, a developer can set their terms and service URL for their app, which Twitter configured to be: ([https?:])\w+

Unfortunately the regexp is missing a ^ char in the start  making malicious URLs like data:CONTENT#https:// work -- so we got HTML Injection, but almost useless for a practical attack because of the CSP rules. After checking the header, I noticed there are multiple CSP misconfigurations in the script-src and object-src blocks, making it possible to bypass CSP in twitter.com. The CSP Rule looks like:

script-src https://connect.facebook.net https://cm.g.doubleclick.net https://ssl.google-analytics.com https://graph.facebook.com https://twitter.com 'unsafe-eval' ‘unsafe-inline’ https://*.twimg.com https://api.twitter.com https://analytics.twitter.com https://publish.twitter.com https://ton.twitter.com https://syndication.twitter.com https://www.google.com;frame-ancestors 'self';object-src https://twitter.com https://pbs.twimg.com; default-src 'self';...

Looking at this, the object-src and the script-src blocks got my immediate attention.
After some research, I saw one of the trusted domains (cdn.syndication.twimg.com aka syndication.twitter.com) hosts JSONP endpoints.

Originally I thought, by exploiting the object-src block (https://pbs.twimg.com) --  one can upload a Flash file (as picture/video extension with few bytes header) to Twitter CDN -- refer it to as an embedded Object to gain code execution. However, because of character limitation, the payload I was trying to make was too long and being cut off, so this method wasn't practical as we were working on a limited payload space. At this point, I sticked to the JSONP bypass for the script-src blocks and started playing with multiple parameters until I found a shorter version, when injected generating an alert in twitter.com.

http://syndication.twitter.com/widgets/timelines/246079887021051904?dnt=true&domain=site.com&lang=en&callback=alert

The above JSONP response from syndication.twitter.com comes back with a Content-Disposition header forcing a download. However, browsers like Chrome still execute the returned file even when returned as an attachment. At this point, this misconfiguration added with the ‘unsafe-inline’ CSP block -- meant we are able to execute code.

By setting the Terms & Services URL of an App to


A developer will be able to pop-up an alert.

POC

After some digging I noticed ssl.google-analytics.com, www.google.com and even graph.facebook.com host JSONP endpoints -- which I wrote to twitter over email -- but will not be fixed anytime soon because it may break the sites usage and call to these sites and performance.

Edit: Ben Hayak mentioned we can use same origin method execution (SOME) attack to manipulate the page as we like: https://syndication.twitter.com/widgets/timelines/246079887021051904?callback=document.body.firstElementChild.Reference.submit -- as used by my Instagram XSS.

I hope it was a fun read,  :) --

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 http://google.com worked but since schemes weren't validated, so did javascript://google.com. 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://google.com/?x=%0Aalert`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:  


document.body.firstElementChild.children[0].firstElementChild.firstElementChild.nextElementSibling.nextElementSibling.nextElementSibling.children[2].children[1].firstElementChild[4].click


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:

javascript://google.com/?x=%0Aalert`Hi!`;document.body.firstElementChild.children[0].firstElementChild.firstElementChild.nextElementSibling.nextElementSibling.nextElementSibling.children[2].children[1].firstElementChild[4].click


PoC:



Report Timeline

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