CVE-2021-21706
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 zip extension provides the ZipArchive class for reading, writing and extracting ZIP archives.
A Path Traversal vulnerability (CVE-2021-21706) has been identified in ZipArchive::extractTo(), which allows an attacker who supplies a crafted ZIP archive to a PHP application on Windows to have files written outside the destination directory, creating or overwriting files wherever the PHP process has permission. PHP tracks this issue as bug #81420.
Per MITRE CWE-24: The product uses external input to construct a pathname that should be within a restricted directory, but it does not properly neutralize "../" sequences that can resolve to a location that is outside of that directory.
This issue affects all versions of PHP before 7.3.31, PHP 7.4 before 7.4.24 and PHP 8.0 before 8.0.11, including 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), when running on Microsoft Windows.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/zip) - Affected versions: <7.3.31, >=7.4.0 <7.4.24, >=8.0.0 <8.0.11
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 7.3.31, 7.4.24, 8.0.11
- NES for PHP 5.6.1 (based on PHP 5.6.40)
Vulnerability Info
This Medium-severity vulnerability is found in the zip extension of PHP before 7.3.31, 7.4 before 7.4.24 and 8.0 before 8.0.11, including the End-of-Life PHP 5.6, 7.0, 7.1 and 7.2 release lines, which never received the upstream fix. It only affects PHP running on Microsoft Windows. The PHP project scores it 5.3 under CVSS 3.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N).
Before ZipArchive::extractTo() writes an entry, php_zip_make_relative_path() turns the entry's name into a path relative to the destination directory. In PHP 5.6.40 the function begins:
if (path_len < 1 || path == NULL) {
return NULL;
}
if (IS_SLASH(path[0])) {
return path + 1;
}The only absolute-path check is for a leading slash, which is what an absolute path looks like on Unix. On Windows, absolute paths can take other forms, such as a name that starts with a drive letter. The upstream report also notes that a path starting with a slash is not absolute on Windows but relative to the current volume. An archive entry named with such a path is not reduced to a relative path, so extractTo() writes it outside the destination directory, subject to the file system permissions of the PHP process.
Exploitation needs a PHP application on Windows that extracts a ZIP archive an attacker supplies with ZipArchive::extractTo(). On Linux and other Unix systems the leading slash is the only form of an absolute path, so those builds are not affected. HeroDevs' analysis notes that the NES for PHP 5 Linux builds were not exposed, and the NES for PHP 5 Windows package ships PECL zip 1.22.8, which already contains the same fix (since PECL zip 1.19.5).
The fix uses PHP's portable absolute-path test, which recognizes the Windows forms, and strips the whole absolute prefix:
if (IS_ABSOLUTE_PATH(path, path_len)) {
return path + COPY_WHEN_ABSOLUTE(path) + 1;
}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.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 7.3.31, 7.4.24, 8.0.11, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- vi (hackberry.xyz) (finder)
- Christoph M. Becker (remediation)