Monday, September 6, 2010

PDF XSS (CVE-2010-0190)

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


PDFs support  JavaScript from within the PDF.  Unfortunately, the script executed from within the PDF will not have access to the browsers DOM.  In order to gain access to the browser’s DOM, we have to use the PDF to redirect the browser to a JavaScript URI.  Normally, redirection to JavaScript URIs are blocked by the PDF security routines, however I discovered an easy bypass using octal encoding.  I place the JavaScript payload into an OpenAction for the PDF, using an octal encoded value (\72) for the “:” character.  An example of the OpenAction is presented below:
%PDF-1.1
1 0 obj
<<
/Type /Catalog
/OpenAction <<
/S /URI
/IsMap false
/URI (javascript\72alert("FTW - "+document.domain))
>>

A super simple XSS with PDFs.  When the PDF is opened in the browser, it redirects the browser to a JavaScript URL allowing for XSS.  Mailing out a rigged PDF as an attachment to some friends using OWA would have been an interesting exercise as certain versions of OWA open PDF attachments inline.  Although I encoded the “:” character in the example above, any character in passed to the OpenAction can be encoded and Adobe Reader will handle it.  In fact, octal encoding can be used throughout the PDF in various scripts and actions.  For example, you could encode the entire protocol handler and it would still work:
/URI (\112\101\126\101\123\103\122\111\120\124\72alert(document.domain))

You can even mix and match the encoding, making it extremely difficult for any signature based IDS to detect malicious payloads.
/URI (j\101v\101s\103r\111p\124\72alert(document.domain))

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
}
else
{
// 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.
app.launchURL("http://xs-sniper.com/",true);

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

There was an excellent presentation at PacSec that covered a ton of PDF bugs and Didier Stevens always has interesting PDF stuff.  I hope this helps someone out there!  Happy hunting.

4 comments:

  1. That might make for any easy way to place a webbug in a pdf file. Maybe even add js to close browser too.

    ReplyDelete
  2. Holy crap, that bypass smells of truly horrible code =/

    Also, PDFs don't block vbscript, but I couldn't get VBScript to run unless it was embeded in an html document :(

    ReplyDelete
  3. Yeah, I think Adobe gave up on/forgot about blocking VBScript :) Too bad there are some weird browser quirks that prevent easy exploitation...

    ReplyDelete
  4. [...] PDF XSS (CVE-2010-0190) – xs-sniper.com PDFs support  JavaScript from within the PDF.  Unfortunately, the script executed from within the PDF will not have access to the browsers DOM. [...]

    ReplyDelete