# Authenticated XXE

WordPress core Media Library parsed uploaded .wav XML with LIBXML_NOENT on PHP 8, letting an author-level user trigger XXE to read files and SSRF.

- Payout: hidden
- Severity: medium
- Program: WordPress
- Found by: sonarsource
- Disclosed: 2021-05-18
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/1095645
- Library page: https://bugbountylibrary.com/r/h1%3A1095645
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:bounty platform:hackerone sev:medium tech:php technique:oob-exfil technique:source-review vuln:file-upload vuln:ssrf vuln:xxe

**Target:** WordPress core Media Library XML metadata parser (wp-includes/ID3)
**Root cause:** On PHP 8 the code skipped libxml_disable_entity_loader() assuming XXE was off by default, but still passed LIBXML_NOENT to simplexml_load_string(), which explicitly enables entity substitution.
**Steps:**
1. Host attacker-controlled xxe.dtd on a reachable web server.
2. Craft xxe.wav with external DTD reference; patch the URL at offset 0x000338CD via hex editor.
3. Log in as author and upload xxe.wav to the Media Library.
4. Server parses the file's XML metadata with LIBXML_NOENT, resolving the external entity.
5. Observe /etc/passwd content base64-encoded in the attacker server's access logs.
**How found:** Code review of the PHP 8 compatibility change: noticed the guard was removed on the assumption XXE is disabled by default, but LIBXML_NOENT still enables entity substitution, then traced user-uploaded file content to that parser.
**Exploitation:** Authenticated author uploads a .wav whose embedded XML metadata references an external DTD; the parser resolves the entity and exfiltrates file contents to the attacker's server via an out-of-band HTTP request.
**Escalation:** Chain to SSRF against internal services, DoS via /dev/urandom, or Phar deserialization via phar:// wrapper for potential RCE.
**Insight:** When a security guard is removed for a new runtime version, check every remaining flag on the same call: LIBXML_NOENT re-enables entity substitution even where libxml defaults would block it, so version-gated mitigations can silently regress.

