In this blog post I’ll briefly explain a type of weakness known as XML External Entity (XXE) vulnerabilities and give an example of such a vulnerability that I found in Restlet. Restlet is a popular REST framework used by large organizations such as Sony, Salesforce, Starbucks, Disney and Thomson Reuters.
Details of vulnerability in Restlet (CVE-2017-14868)
This vulnerability affects the SimpleXMLProvider
in Restlet. The affected code allows a remote attacker to potentially access arbitrary files on the system by sending a request with maliciously crafted XML data to a REST API built with Restlet.
If you use a combination of both Restlet and Simple XML then your application is very likely affected. We strongly advise you to urgently upgrade Restlet to version 2.3.11 (or higher).
XML External Entity vulnerabilities
The XML External Entity (XXE) vulnerabilities abuse the XML specification to force an XML parser to either fetch sensitive data from the system, or carry out denial of services (DoS) or server-side request forgery (SSRF) attacks. The main problem is that the XML standard allows an XML document to define entities, which are like variables that can refer to resources outside of the XML document. Let’s consider the following XML document:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY abc SYSTEM "file:///etc/passwd" >]>
<foo>&abc;</foo>
This document defines an external entity named abc
, that refers to the content of the file /etc/passwd
. When the XML document is parsed, the entity &abc;
will be replaced by the content of /etc/passwd
. Now if an application is parsing XML data from an untrusted source, then by defining an external entity that points to a sensitive file, the attacker will be able to force the application to include sensitive data in the parsed XML document. If the attacker can then retrieve the content of the parsed document, they will be able to view the content of /etc/passwd
. This can happen, for example, if the application includes the content of the parsed document in an error message, which is fairly common.
Many XML parsers can be configured to disable the use of entities and their declarations, which is recommended when parsing untrusted data. However, many XML parsers allow entities by default, and often the configuration is unclear and multiple properties need to be set. The OWASP website covers a comprehensive set of XML parsers. By default, CodeQL’s XXE detection query for Java covers all the ones that are mentioned in the OWASP page. There are also two equivalent queries for JavaScript: XML external entity expansion and XML internal entity expansion.
Entity Expansion in Simple XML
Simple XML is a third-party XML parser in Java that parses XML files. I noticed that it is used in Restlet to parse untrusted XML data from http requests and decided to check whether Simple XML is expanding entities when it parses XML input. To do so, I wanted to check whether any XML input parsed within Simple XML was parsed with entities enabled. This can be done easily with CodeQL, as there is already a library XmlParsers
providing the facility for this type of checking. Within XmlParsers
, there is a class called XmlParserCall
, which is an abstraction of method calls that are used for parsing XML input.
/**
* An abstract type representing a call to parse XML files.
*/
abstract class XmlParserCall extends MethodAccess {
/**
* Gets the argument representing the XML content to be parsed.
*/
abstract Expr getSink();
/**
* Holds if the call is safe.
*/
abstract predicate isSafe();
}
A query that searches for instances of this class will return all method calls that parse XML input. In this case, I wanted to look for parsers that expand entities, in other words, for calls that are not safe. In addition, I would also want to exclude the unsafe calls that are used in tests. This can be done by excluding calls in instances of the QL class TestClass
:
from XmlParserCall call
where not (call.isSafe()) and not call.getEnclosingCallable().getDeclaringType() instanceof TestClass
select call
By running another CodeQL query, I found that Simple XML does indeed parse entities in the classes Formatter
, StreamProvider
and DocumentProvider
. What is more is that there seems to be no way for a user to disable entity expansion. I tested it and found that this indeed leads to an exploitable vulnerability in Restlet and reported the issue. The team took this very seriously and did a great job of fixing the issue. Even though Simple XML has ceased development for a number of years and did not respond to the Restlet team, Thierry Boileau went the extra mile to fork and fix (the parsing in Formatter
is also fixed in a later commit after I showed him the result of my query) Simple XML, so now there is a way for everyone to safely use Simple XML!
Vendor response
-
15 Aug 2017: Initial private disclosure to Restlet
-
17 Aug 2017: Initial response
-
28 Sept 2017: CVE ID requested
-
28 Sept 2017: Patch available
-
29 Sept 2017: Public disclosure with Fixed version released
Mitigation of XXE risk
In this post I briefly explained the simplest form of XXE and gave the vulnerability in Restlet as an example. This is a very simple form of XXE that leads to information disclosure. I will talk more about other subtle forms of XXE in other blog posts, and will use more examples to illustrate the problems.
In general, to mitigate the risk of XXE, make sure that when using an XML parser on untrusted data, the parser is configured according to the specifications in OWASP. Also, if your application is using SimpleXML
as a parser for untrusted data, consider using the safe version in Restlet.
Note: This post was originally published on LGTM.com on October 02, 2017