CVE-2019-11045
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 Standard PHP Library (SPL) extension, which is always built, provides the DirectoryIterator class and its subclasses for listing the contents of a directory.
An Improper Input Validation vulnerability (CVE-2019-11045) has been identified in the constructors of PHP's DirectoryIterator, FilesystemIterator, RecursiveDirectoryIterator and GlobIterator classes, which allows an attacker who can influence a directory path to embed a NUL byte in it, so that the application checks one path but PHP lists the directory named by the part before the NUL byte. PHP tracks this issue as bug #78863.
Per OWASP: The Embedding NULL Bytes/characters technique exploits applications that don’t properly handle postfix NULL terminators. This technique can be used to perform other attacks such as directory browsing, path traversal, SQL injection, execution of arbitrary code, and others.
This issue affects PHP before 7.2.26, PHP 7.3 before 7.3.13 and PHP 7.4.0, which includes every End-of-Life release line from PHP 5.6 through 7.1, each through its final release.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/spl) - Affected versions: <7.2.26, >=7.3.0 <7.3.13, >=7.4.0 <7.4.1
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 7.2.26, 7.3.13, 7.4.1
- NES for PHP 5.6.1 (based on PHP 5.6.40)
Vulnerability Info
This Low-severity vulnerability is found in the SPL extension of PHP before 7.2.26, 7.3 before 7.3.13 and 7.4.0, including every End-of-Life release line from PHP 5.6 through 7.1, which never received the upstream fix. The PHP project scores it 3.7 under CVSS 3.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N) and classifies it as CWE-170, Improper Null Termination.
PHP strings can contain NUL bytes, but the operating system calls that open a directory treat a NUL byte as the end of the path. Functions that take a file system path are expected to reject a string that contains one. The constructor shared by the SPL directory iterators parsed its path argument as an arbitrary string instead. Before the fix, spl_filesystem_object_construct() reads:
if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &path, &len, &flags);
} else {
flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &path, &len);
}With the s format, a path such as allowed/dir followed by a NUL byte and more text is accepted whole, and the directory opened is the one named by the text before the NUL byte. Code that validates the full string with string functions, for example by checking that it ends with or contains an allowed directory name, can therefore approve one path while PHP lists a different directory. The CVE record describes the impact as vulnerabilities in applications that check which paths the code is allowed to access, and the CNA rates the confidentiality impact as low.
Exploitation needs application code that builds a directory path from attacker-influenced input, checks it with string operations, and then passes it to one of the affected iterator classes. HeroDevs' analysis notes that the SPL extension is always built, so the issue is reachable from any server API. Applications that do not pass user-influenced paths to these classes, or that reject NUL bytes in input before using it, are not exposed.
The fix parses the argument with the p (path) format, which rejects strings that contain NUL bytes, so the constructors throw UnexpectedValueException instead of opening a truncated path:
parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &path, &len, &flags);Mitigation
The PHP project publishes security fixes only for its supported release lines. PHP 5.6, 7.0 and 7.1 are End-of-Life and will not receive any public updates to address this issue.
Until an upgrade is possible, reject any input that contains a NUL byte before using it to build a path, and validate the resolved path (for example with realpath()) rather than the raw string.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 7.2.26, 7.3.13, 7.4.1, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- ryat (finder)
- Christoph M. Becker (remediation)