I assume that everyone in their professional career has heard about XML. To be honest, it’s so widely used that it’s hard to miss. Simple structure, a little too verbose, yet easy to understand. You might think it is so easy and well-known, that there are no secrets and certainly no vulnerabilities! I will try to put you right in this post.

1. XML internal entities

I’m pretty sure you already know that if you want to use special characters that cannot be typed into an XML document (<, &) you need to use the entity reference (< &). But did you know that you can define your own internal entity? It’s pretty easy. Take a look:

As you can see, all we need to do is to write the doctype declaration and define the custom entity in it. After that, we can use our new internal entity in an XML document. As a result, the parser will replace every &company; occurrence with ‘Pragmatists’ text. Unfortunately, this feature puts us in danger.

2. Billion laughs attack

Firstly, let’s take a look at the very simple, yet dangerous denial of service (DoS) attack called the Billion laughs attack.

In order to carry out the attack, you need to prepare malicious XML using internal entities described in the previous paragraph, and use it as an input.

When an XML parser loads this document, it will try to resolve the lol9 entity. At first, lol9 expands to ten lol8 entities, each lol8 expands to ten lol7 entities and so on. As a result, we get 1 billion “lol” strings. This creates a heavy burden on our machine, which can bury application responsiveness! If it doesn’t sound scary to you, imagine that on my computer memory consumption increased up to 4GB in one minute.

NOTE:

In order to simulate that attack, I wrote a simple Java app. During tests, however, I encountered a Java error.

[Fatal Error] :1:1: JAXP00010001: The parser has encountered more than “64000” entity expansions in this document; this is the limit imposed by the JDK.

It seems that the default Java XML parser (at least in Java 8) is immune to the Billion Laughs Attack. Nevertheless, I was a little surprised because I’d tried that code earlier on another computer and was able to succeed.

I started to dig around and discovered that the method I was using to get DocumentBuilder can return different instances depending on its lookup procedure.

When I added maven dependency with some old XML parser, DocumentBuilderFactory.newInstance() returned a different implementation, and I was able to get the expected result. It’s important to be aware that even if you are safe at present, someone in the future can add simple dependency to your project, causing a security breach.

Here you can find code used to create the Document from String:

NOTE 2:

There is another variation of this attack called quadratic blowup. This causes quadratic growth in storage requirements (Billion laughs takes an exponential amount of space).

The only difference is that instead of using nested entities, you can define one very large entity and repeat it over and over again.

3. XML external entity (XXE)

In paragraph 2, we saw an entity that was defined in a document, but there is another way to use entities. We can import them from another file.

It looks simple but it is even more tricky than internal entities, and can lead to XXE attacks. To understand it better, imagine that we have two endpoints: one for listing all posts and one for creating new posts. With this in mind, we can prepare malicious XML input and use endpoint to create a new post. The input data could look like this:

After that, we can use another endpoint to list all posts. If all goes well, the response will look like this:

As you can see, this is really dangerous and can lead to serious security problems!

NOTE:

Imagine that we use a different XML structure to create a post. In this example, we will use the element’s attributes to describe author, topic, content instead of nested elements (as in previous examples).

Unfortunately, there is one constraint when you use external entities: you cannot use them in XML attributes, but that doesn’t mean there is no way to attack our application. If we are stubborn enough, we can try to workaround that problem with parameter entities.

Parameter entities are defined using % signs, and can only be used in DOCTYPE declarations. Moreover, they can be external.

Sample parameter entity usage:

If we want to attack our sample application, we need to try a little harder. Firstly, we need to create an external file with parameter entity definitions.

Secondly, we need to refer to that file and use parameterEntityDefiningEntity in order to define entityWithResult.

Finally, we can use entities in attributes, create new posts, list all of them and enjoy the outcome.

NOTE 2:

You might think you are safe if you don’t provide an endpoint that can return data (like listing posts in the previous example) but that’s not true. Instead of providing the file with external entity definition, we can prepare an endpoint that listens to every request and logs results.

NOTE 3:

The previous example had a small simplification. Referring to http://yourserver/log?%result; will work only if the result is on one line, otherwise we will get an error because the URL won’t be correct. In fact, previous XXE examples had small constraints as well. Every file that we read and append as a result needs to be a grammatically valid in XML context and cannot contain \x00 bytes.

Nevertheless, sometimes we can overcome these problems. In PHP, for example, we could use a filter to encode the result, or even execute the code remotely.

4. Protection

As always, everything depends on what technology you are using. Securing your application can be as easy as configuring the library or setting a couple of properties. Sadly, most Java XML parsers have XXE enabled by default.

On the OWASP site, you can read more about ways to prevent XXE attacks.