XML external entity injection (also known as XXE) is a web security vulnerability that allows an attacker to interfere with an application’s processing of XML data. It often allows an attacker to view files on the application server filesystem, and to interact with any back-end or external systems that the application itself can access, and in the case of PHP can lead to Command Execution.
So what is an XML Entity?
An XML entity is a way of representing an item of data in an XML Document. There are many pre-defined internal entities such as
& for ampersand (&) and
< and > for < and > respectively. These characters if placed directly in an XML document may alter XML Tags and data so need to be represented as the entity.
What are custom entities?
XML provides us a way to use a Document Type Definition (DTD) to declare the structure of an XML document. It provides us with the ability to provide custom types using the
DOCTYPE element at the start of of a Document.
XML also allows custom entities to be defined within the DTD using the
ENTITY element when defining a doctype. For example :
This document definition will replace any references to
&customentity; with the string “Hello World”.
What is an external entity?
An External Entity is a custom entity that relies on a definition that is not part of the DTD. To do this when we define an entity we can use the
SYSTEM keyword. For example :
With this definition we replace the
&customentity; reference with the contents of the url defined.
This is very useful if you intent to perform an SSRF attack from the XML processor
How can we exploit this?
When we find a target using XML to transmit data we can intercept this request, or submit a modified XML document, or even an SVG or DOCX, with an external entity.
As we know from earlier we can define an external entity using the SYSTEM keyword to call a URL, This has many advantages and gives us the ability to call other protocol handlers registered on the system.
By making use of the
file:// protocol handler we can then extract the contents of a file on the system.
For example the following XML document will read the content of /etc/passwd when passed to a vulnerable XML Handler.
if we post this to a vulnerable application the contents of the file are displayed
$ curl -X POST -d @xml-document.xml http://localhost:8080 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin ...
Most languages do not have a method of performing OS Command Execution from XML processors, However with PHP thats a little different when the expect module is enabled.
The expect module registers a PHP wrapper (
expect://) that can be used to run OS commands.
If we modify the above XML document to run an OS command like
id it will dump out the
STDOUT contents from the command.
$ curl -X POST -d @xml/exect.xml http://localhost:8080 uid=33(www-data) gid=33(www-data) groups=33(www-data)
As we learned XML can be exploited using External Entities to exfiltrate data and in some cases can lead to command execution.
I’ve uploaded the demo PHP application and Dockerfile to Github so you can try this out for yourself, I’ve also included an exploit script written in python.
If you enjoyed this guide feel free to Buy me a coffee!