CVE-2019-11044
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 link() function creates a hard link to an existing file.
An Improper Input Validation vulnerability (CVE-2019-11044) has been identified in the Windows implementation of PHP's link() function, which allows an attacker who controls part of a file name passed to link() to embed a NUL byte so that PHP silently uses only the part of the name before it, bypassing checks an application made on the whole name. PHP tracks this issue as bug #78862.
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 PHP on Windows: all versions of PHP before 7.2.26, PHP 7.3 before 7.3.13 and PHP 7.4.0, which includes the End-of-Life PHP 5.6, 7.0 and 7.1 release lines through their final releases (5.6.40, 7.0.33 and 7.1.33).
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/standard) - Affected versions: <7.2.26, >=7.3.0 <7.3.13, >=7.4.0 <7.4.1 (Windows only)
- 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.2 (based on PHP 5.6.40)
Vulnerability Info
This Low-severity vulnerability is found in the Windows builds of all PHP versions before 7.2.26, 7.3 before 7.3.13 and 7.4.0, including the End-of-Life PHP 5.6, 7.0 and 7.1 release lines, 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).
PHP strings can contain NUL bytes, but the operating system calls that work with files treat a NUL byte as the end of the name. For that reason PHP functions that take file names parse them with the p (path) specifier, which rejects any string that contains a NUL byte. On Windows, link() is implemented separately from other platforms, and in PHP 5.6.40 it parses both names as plain strings:
/*First argument to link function is the target and hence should go to frompath
Second argument to link function is the link itself and hence should go to topath */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &frompath, &frompath_len, &topath, &topath_len) == FAILURE) {
return;
}Everything that follows, including the open_basedir checks and the Windows CreateHardLinkA() call, works on the names as C strings and so stops at the first NUL byte. A name with an embedded NUL byte is therefore accepted without any warning, and the link is made using only the text before that byte. An application that checks a name it builds from user input, for example by testing its extension or a suffix, before passing it to link(), may approve a name whose effective part, the text before the NUL byte, points somewhere else.
Only the Windows builds of PHP are affected: the code lives in a Windows-only source file, and the Linux and other Unix builds use a different implementation that already rejects NUL bytes, so they are not exposed. On Windows, exploitation needs an application that passes attacker-influenced text to link() and relies on its own checks of the full name, under any SAPI.
The fix parses both arguments as paths, so link() refuses a name that contains a NUL byte. In the upstream fix it reads:
if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &frompath, &frompath_len, &topath, &topath_len) == FAILURE) {
return;
}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 file name that contains a NUL byte before passing it to link().
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)