XXE (XML External Entity) Attack & Prevention
Tags: security, webdev, cybersecurity, programming
Published: 2021-02-18 08:32:39

The original posting can be found [here](https://www.appsecmonkey.com/blog/xxe-attack-and-prevention/).

## What are XXE vulnerabilities?
XXE (XML External Entity) vulnerabilities arise when untrusted data is passed to a misconfigured XML parser.

The XML protocol includes features for accessing files and network resources. If your XML parser has not been configured to disable these dangerous features, it could open a path for an attacker to access files on your server's disk and resources on your internal network.

## How to prevent XXE vulnerabilities?
Follow these steps: 

1. Use a well-known XML library with a good security record.
2. Configure the library so that dangerous features (external entities, document type definitions, and xinclude) are disabled.
3. As an additional layer of security, use a web application firewall (WAF) product in front of your web application, validate input, harden your infrastructure, restrict egress connections, minimize file permissions and handle errors properly.

## A simple example

Let's say that you have a XML API for receiving pizza orders. A user of the API could submit the order like so: 

```xml
<pizza>
  <size>
    Large
  </size>
  <toppings>
    <topping>Mozzarella</topping>
    <topping>Salami</topping>
  </toppings>
</pizza>
```

> <i class="fa fa-check"></i> Order received with the following toppings: Mozzarella, Salami

## XML Entities
XML protocol supports variables, called *entities*, which are defined inside a DTD (Document Type Definition). So, the user could also submit the toppings as entities: 

```xml
<!DOCTYPE pizza[
  <!ENTITY topping1 "Mozzarella">
  <!ENTITY topping2 "Salami">
]>
<pizza>
  <size>
    Large
  </size>
  <toppings>
    <topping>&topping1;</topping>
    <topping>&topping2;</topping>
  </toppings>
</pizza>
```

> <i class="fa fa-check"></i> Order received with the following toppings: Mozzarella, Salami

## The "Billion Laughs" Attack

There are some risks with handling even these basic entities. How would the server like processing an XML document like this? 

```XML
<!DOCTYPE pizza[
  <!ENTITY a "billion laughs">
  <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
  <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
  <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
  <!ENTITY e "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
  <!ENTITY f "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
  <!ENTITY g "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
  <!ENTITY topping1 "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
  <!ENTITY topping2 "Salami">
]>
<pizza>
  <size>
    Large
  </size>
  <toppings>
    <topping>&topping1;</topping>
    <topping>&topping2;</topping>
  </toppings>
</pizza>
```

The answer is: the server wouldn't like it at all. Parsing this exponentially expanding document could consume all of the server's resources and cause a denial of service condition. This is generally known as the "billion laughs" attack (I think because the original poc was like &amp;lol1;&amp;lol1;...).

## XML External Entities
Now it gets dangerous. XML also supports including other XML documents from *external sources*, specified by an URI. Look at this: 

```xhtml
<!DOCTYPE pizza[
  <!ENTITY topping1 "Mozzarella">
  <!ENTITY topping2 SYSTEM "file:///etc/passwd">
]>
<pizza>
  <size>
    Large
  </size>
  <toppings>
    <topping>&topping1;</topping>
    <topping>&topping2;</topping>
  </toppings>
</pizza>
```

```
Order received with the following toppings: Mozzarella, root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/...
```

Oops. Or what about this?

```XML
<!DOCTYPE pizza[
  <!ENTITY topping1 "Mozzarella">
  <!ENTITY topping2 SYSTEM "http://secret-internal-api.local/admin/all-the-sensitive-things/">
]>
<pizza>
  <size>
    Large
  </size>
  <toppings>
    <topping>&topping1;</topping>
    <topping>&topping2;</topping>
  </toppings>
</pizza>
```

> <i class="fa fa-check"></i> Order received with the following toppings: Mozzarella, {"allTheSensitiveThings": ["secrets"...

## It's not just SYSTEM "file://..."

There are other ways to include external files in XML documents than the *general external entities* we have looked at so far.

First of all, you can use `PUBLIC` instead of `SYSTEM`.

```XML
  <!ENTITY topping2 PUBLIC "file:///etc/passwd">
```

And you can have *parameter entities* instead of general ones: 

```xml
<!ENTITY % topping2 SYSTEM "file:///etc/passwd">
```

And sometimes you can also use [XInclude](https://www.xml.com/pub/a/2002/07/31/xinclude.html) to refer to external resources.
```xml
 <xi:include href="file:///etc/passwd"/>
```

Also, you generally don't need to have the `file://`, this will do: 
```XML
<!ENTITY topping2 SYSTEM "/etc/passwd">
```

And sometimes, most commonly in Java, directory listings work perfectly well.
```XML
<!ENTITY topping2 SYSTEM "file:///">
```
> <i class="fa fa-check"></i> Order received with the following toppings: Mozzarella, /bin /boot /cdrom /dev /etc/ /home...

*Writing* to the filesystem, although a bit limited, can sometimes be possible with the `jar://` protocol (also a courtesy of Java implementations).

Finally, there are rare cases such as PHP's [expect://](https://www.php.net/manual/en/wrappers.expect.php) protocol which can enable OS command execution through XXE vulnerabilities.

## The output doesn't have to be reflected
This is not an exploitation guide, but it's good to know that so-called *blind* XXE vulnerabilities can be exploited perfectly well. The attacker can craft an XML document that reads e.g. a file and then sends it over to the attacker's server.

And at any rate, there are other ways in which XXE vulnerabilities can be reflected. For instance, error messages can often be used for this purpose.

## Preventing XML entity vulnerabilities
To prevent these vulnerabilities in your application, use a good XML parser and configure it properly: 
- Disable document type definitions (DTD) altogether. This will also prevent the billion laughs attack.
- Disable general external entity processing.
- Disable parameter entity processing.
- Disable XInclude support.

It generally looks more or less like this: 

```java
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
```

OWASP has curated a list of how to do this for different parsers: [OWASP XXE Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html). 

Also, there are software libraries that provide you with XML parsers that have already been secured, such as [defusedxml](https://pypi.org/project/defusedxml/) for Python.

## Hardening against XML entity vulnerabilities
There are a couple of things that you should do **in addition** to the steps in the previous section, to get a nice layered security model.

1. Use a WAF (Web Application Firewall) product such as ModSecurity + CRS to prevent obviously malicious input from reaching your application.
2. Validate all input in your application to prevent obviously invalid input from reaching your XML parsing logic. Validating XML before parsing it can seem daunting, but it doesn't have to be a very complex regex pattern to already make attacks much harder.
3. Handle errors properly. Don't show stack traces etc. developer information to users and in general the more data you reflect the more chances of an attacker successfully exploiting XXE.
4. Restrict egress traffic from your application server to both the outside world and your internal network. If reflection doesn't work, the attacker is usually left with sending files, etc. to the attacker's server and scanning your internal network for interesting hosts/ports. Don't allow either of these. And note that DNS can be used to exfiltrate, so block arbitrary DNS as well. Either get rid of DNS altogether and use a local hosts-file or configure your upstream DNS server with a private zone to only resolve specific hostnames.
5. Keep your application user's filesystem permissions at a minimum.
6. Secure your infrastructure. Use authentication and encryption in all internal connections so that SSRF (Server-Side Request Forgery, that is, sending e.g. arbitrary HTTP requests to internal hosts) cannot be used for anything useful.

## Know where you parse XML
Sometimes you parse XML without knowing it. For example, did you know that Office documents are zipped XML? And that SVG images are XML?

There was an [interesting case on Hackerone](https://hackerone.com/reports/836877) where the XMP metadata of a JPG file was getting parsed unsafely. There are [many other interesting XXE bugs](https://github.com/reddelexc/hackerone-reports/blob/master/tops_by_bug_type/TOPXXE.md) there as well if you want to take a look.

## Conclusion
XXE vulnerabilities are a serious risk, but you can prevent them by using a good XML parser and configuring it properly. As always, additional layers of security are recommended. These include using a WAF product, input validation, proper error handling, securing your infrastructure, minimizing filesystem permissions, and restricting egress network traffic.

## Get the web security checklist spreadsheet!
[![Subscribe](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iqd1ef4a5a0icyvvk65.jpg)](https://eepurl.com/hqAGt5)
 ☝️ [Subscribe](https://eepurl.com/hqAGt5) to AppSec Monkey's email list, get our best content delivered straight to your inbox, and <b>get our 2021 Web Application Security Checklist Spreadsheet for FREE</b> as a welcome gift!

## Don't stop here
If you like this article, check out the other application security guides we have on [AppSec Monkey](https://www.appsecmonkey.com/) as well.

Thanks for reading.