CVE-2021-21707

Improper Input Validation (4.16)
Affects
PHP
in
PHP
No items found.
Versions
<7.3.33, >=7.4.0 <7.4.26, >=8.0.0 <8.0.13

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 libxml-based extensions (dom, simplexml, xmlreader and others) parse XML documents and can load them directly from a file path or URL.

An Improper Input Validation vulnerability (CVE-2021-21707) has been identified in the file loading code shared by PHP's libxml-based XML extensions, which allows an attacker who can influence a file path that an application passes to functions such as simplexml_load_file() or DOMDocument::load() to make the function stop reading the path at an encoded NUL byte, so that a different file is loaded than the one the application checked. PHP tracks this issue as bug #79971.

Per MITRE CWE-158: The product receives input from an upstream component, but it does not neutralize or incorrectly neutralizes NUL characters or null bytes when they are sent to a downstream component.

This issue affects all versions of PHP before 7.3.33, PHP 7.4 before 7.4.26 and PHP 8.0 before 8.0.13, which includes the End-of-Life release lines PHP 5.6, 7.0, 7.1 and 7.2 through their final releases (5.6.40, 7.0.33, 7.1.33 and 7.2.34).

Details

Module Info

Vulnerability Info

This Medium-severity vulnerability is found in the XML extensions of all versions of PHP before 7.3.33, PHP 7.4 before 7.4.26 and PHP 8.0 before 8.0.13, including the End-of-Life PHP 5.6, 7.0, 7.1 and 7.2 release lines, which never received the upstream fix. The PHP project scores it 5.3 under CVSS 3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N).

Functions such as simplexml_load_file(), DOMDocument::load(), DOMDocument::loadHTMLFile() and XMLReader::open() take a file name, but libxml2 treats it as a URI. PHP's stream opener for libxml, php_libxml_streams_IO_open_wrapper(), parses the value as a URI and, for local paths and file: URIs, URL-decodes it with xmlURIUnescapeString() before opening the result. A path that contains %00 is decoded into a string with a NUL byte in it, and everything after that byte is ignored when the file is opened. The reporter showed that inserting poc-1.xml%00 into a path makes simplexml_load_file() load poc-1.xml and ignore the rest of the path.

An application that builds a path from user input and validates it as a whole, for example by checking its extension or suffix with string functions, can therefore be tricked into loading another file it did not intend to read. The CVE record notes that this may lead to reading a different file than intended. HeroDevs' analysis puts the exposure in any SAPI with the libxml-based extensions, in code that loads an XML file whose path an attacker influences after validating it with string functions. For the PHP 5.6 line, the analysis covers NUL bytes in such paths in general and also lists SoapClient's WSDL loading among the affected paths. Applications that load XML only from fixed paths, or that read the file themselves and pass its contents to simplexml_load_string() or DOMDocument::loadXML(), are not affected.

The fix rejects any URI that contains a percent-encoded NUL byte before it is decoded, so the load fails with a warning instead of opening a truncated path:

if (strstr(filename, "%00")) {
    php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
    return NULL;
}

uri = xmlParseURI(filename);
if (uri && (uri->scheme == NULL ||
        (xmlStrncmp(BAD_CAST uri->scheme, BAD_CAST "file", 4) == 0))) {
    resolved_path = xmlURIUnescapeString(filename, 0, NULL);

The same check is added to the output path used when libxml writes documents to a file.

Mitigation

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

Until an upgrade is possible, reject user-influenced paths that contain %00 or a NUL byte before passing them to the XML functions, or read the file with PHP's own file functions and parse the contents with simplexml_load_string() or DOMDocument::loadXML().

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

  • Upgrade to PHP 7.3.33, 7.4.26, 8.0.13, 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
Medium
ID
CVE-2021-21707
PROJECT Affected
PHP
Versions Affected
<7.3.33, >=7.4.0 <7.4.26, >=8.0.0 <8.0.13
NES Versions Affected
Published date
November 29, 2021
≈ Fix date
November 18, 2021
Fixed in
Category
Improper Input Validation (4.16)
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.