Authenticated XXE
- Reported to Wordpress
- Reported by SonarSource
- Medium (6.9)
- $600
- Published 4 years ago
- No Likes
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:
- 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).
- 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). - Put the file xxe.dtd at the root of the webserver that you control.
- Login to WordPress as author and upload xxe.wav in the media library.
- 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
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.
Attachments
- F1183994: xxe.zip
- F1183995: screenshot.png