Authenticated XXE
Medium
W
WordPress
Submitted None
Actions:
Reported by
sonarsource
Vulnerability Details
Technical details and impact analysis
## Description:
The WordPress core Media Library does not securely parse XML content when running on PHP 8. By uploading a malicious .wav file, an authenticated attacker can trigger a XXE vulnerability which enables to read secret system files, DoS the web server, perform SSRF, or aim at Remote Code Execution via Phar Deserialization.
## Steps To Reproduce:
Requirements:
* latest WordPress 5.6 installation
* running on PHP 8
* *author* user privileges in WordPress, or higher
* another web server that is controlled by the attacker to retrieve leaked data
The vulnerability can be exploited by uploading a crafted .wav file. The attached archive contains such a .wav file with a payload for extracting the content of */etc/passwd* by loading an external DTD. To reproduce:
1. Adapt the address in the 2 files in the attached PoC archive to point to a web server that you control (and that is reachable from the targeted WordPress installation).
2. For the .wav file, the address has to be adapted at `0x000338CD` (best use a hex editor for this, doing that with a text editor might corrupt the file).
3. Put the file *xxe.dtd* at the root of the webserver that you control.
4. Login to WordPress as author and upload *xxe.wav* in the media library.
5. The content of */etc/passwd* will appear in the access logs of the web server base64 encoded (see attached screenshot).
## Vulnerable Code:
The vulnerable code commit is the following:
https://github.com/WordPress/WordPress/commit/03eba7beb2f5b96bd341255eaa30d6b612e62507
The vulnerable code is:
```
if (PHP_VERSION_ID < 80000) {
// http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
// https://core.trac.wordpress.org/changeset/29378
// This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
// disabled by default, so this function is no longer needed to protect against XXE attacks.
$loader = libxml_disable_entity_loader(true);
}
$XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT);
```
It was recently modified to accommodate for the deprecation of the `libxml_disable_entity_loader()` function in PHP 8. The mistake here is to rely on the fact that XXE is no longer possible by default in PHP 8 (as it requires libxml version > 2.9). This is true, but using the `LIBXML_NOENT` flag is certainly not the default. The flag explicitly activates entity substitution (the name of the flag might be a little misleading). So if user input reaches that point as part of the `$XMLstring` variable, XXE is possible.
## Impact
An attacker can:
- read secret system files, such as *.htaccess* or *wp-config.php*
- DoS the web server via a malicious XML document, or by loading */dev/urandom* via XXE
- fingerprint and exploit services in the internal network by turning the XXE into SSRF
- trigger a Phar Deserialization by using the `phar://` stream wrapper within the XXE which can lead to further vulnerabilities, depending on the gadget chains available in the WordPress core and its plugins.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
XML External Entities (XXE)