CVE-2023-3823

Information Exposure
Affects
PHP
in
PHP
No items found.
Versions
<8.0.30, >=8.1.0 <8.1.22, >=8.2.0 <8.2.8

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

PHP is a general-purpose scripting language used mostly for web development. It runs behind web servers through server APIs such as Apache mod_php and PHP-FPM, and powers content management systems and frameworks such as WordPress, Drupal, Moodle and Laravel. Its XML extensions (DOM, SimpleXML, XMLReader, XML, SOAP and XSL) parse documents with the libxml2 library.

An Information Exposure vulnerability (CVE-2023-3823) has been identified in the way PHP's XML extensions set up libxml2 parsers, which allows an attacker who can supply XML to an application to have external entities loaded and local files disclosed, even though the application never enabled entity loading, when other code in the same process has changed libxml2's process-wide parser defaults. PHP tracks this issue as GHSA-3qrf-m4j2-pcrr.

Per MITRE CWE-611: The product processes an XML document that can contain XML entities with URIs that resolve to documents outside of the intended sphere of control, causing the product to embed incorrect documents into its output.

This issue affects all versions of PHP before 8.0.30, PHP 8.1 before 8.1.22 and PHP 8.2 before 8.2.8, which includes every End-of-Life release line from PHP 5.6 through 7.4, each up to its final release.

Details

Module Info

Vulnerability Info

This High-severity vulnerability is found in the libxml2-based XML extensions of all PHP versions before 8.0.30, 8.1 before 8.1.22 and 8.2 before 8.2.8, including every End-of-Life release line from PHP 5.6 through 7.4, which never received the upstream fix. The PHP project scores it 8.6 under CVSS 3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:L).

To parse a document, PHP creates a libxml2 parser context and sets the options the application asked for, such as LIBXML_NOENT to substitute entities or LIBXML_DTDLOAD to load external DTDs. libxml2 also keeps process-wide defaults, for example the one set by xmlSubstituteEntitiesDefault(1), and copies them into every new parser context. As the upstream fix explains, a default set this way is added to the parsing options every time a context is created, even if the application never requested it.

PHP assumed these defaults were unchanged. Other code in the same process, such as the ImageMagick-based imagick extension named in the CVE record or another library built on libxml2, can change them for its own purposes and leave entity substitution or external DTD loading enabled. PHP's parsers then load external entities from attacker-supplied XML, which can disclose any local file the PHP process can read. Because the defaults are process-wide, the state can persist across many requests handled by the same process until it exits. The reporters found that it reproduced only intermittently, on some requests and not others.

Exploitation needs an application that parses attacker-supplied XML with DOM, SimpleXML, XMLReader, the XML parser, SOAP or XSL, under any server API, in a process where other code has changed libxml2's global defaults and left them changed. The attacker needs no account if the XML arrives through an unauthenticated request. Processes in which nothing changes libxml2's defaults behave as the application requested, and options that the application sets explicitly keep working after the fix.

The fix sets the parser options to known values before each parse. For APIs that work on a parser context, it uses a helper that resets the context's options; for APIs that rely on the global defaults, it saves, resets and later restores them. The context helper reads:

static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt)
{
    ctxt->loadsubset = 0;
    ctxt->validate = 0;
    ctxt->pedantic = 0;
    ctxt->replaceEntities = 0;
    ctxt->linenumbers = 0;
    ctxt->keepBlanks = 1;
    ctxt->options = 0;
}

Entity loading that the application requests explicitly, for example with LIBXML_NOENT, keeps working after the fix. HeroDevs' analysis notes one visible change on PHP 5.6 built against libxml2 older than 2.9.5, as on RHEL 7 or Ubuntu 16.04: DOMDocument::loadHTML() and loadHTMLFile() now keep whitespace between the <html> and <head> elements, as newer libxml2 versions already do. Passing LIBXML_NOBLANKS removes it.

Mitigation

The PHP project publishes security fixes only for its supported release lines. PHP 5.6, 7.0, 7.1, 7.2, 7.3 and 7.4 are End-of-Life and will not receive any public updates to address this issue.

Until an upgrade is possible, avoid loading extensions or libraries that change libxml2's global defaults, such as imagick, in PHP processes that parse untrusted XML.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to PHP 8.0.30, 8.1.22, 8.2.8, or later.
  • Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.

Credits

Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2023-3823
PROJECT Affected
PHP
Versions Affected
<8.0.30, >=8.1.0 <8.1.22, >=8.2.0 <8.2.8
NES Versions Affected
Published date
August 11, 2023
≈ Fix date
August 3, 2023
Fixed in
Category
Information Exposure
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
PHP
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.