CVE-2023-0568
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.
A Buffer Overflow vulnerability (CVE-2023-0568) has been identified in PHP's core path resolution code, used by open_basedir checks and by the DOM and XMLReader extensions, which allows an attacker who can influence a file path or working directory of the maximum supported length to make PHP write a NUL byte one position past the end of a stack buffer, which can crash PHP and might lead to unauthorized data access or modification. PHP tracks this issue as bug #81746.
Per MITRE CWE-131: The product does not correctly calculate the size to be used when allocating a buffer, which could lead to a buffer overflow.
This issue affects all versions of PHP before 8.0.28, PHP 8.1 before 8.1.16 and PHP 8.2 before 8.2.3, which includes the End-of-Life PHP 5.6, 7.0, 7.1, 7.2, 7.3 and 7.4 release lines through their final releases.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(main/fopen_wrappers.c,ext/dom,ext/xmlreader) - Affected versions: <8.0.28, >=8.1.0 <8.1.16, >=8.2.0 <8.2.3
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 8.0.28, 8.1.16, 8.2.3
- NES for PHP 5.6.1 (based on PHP 5.6.40)
- NES for PHP 7.2.1 (based on PHP 7.2.34)
- NES for PHP 7.4.1 (based on PHP 7.4.33)
Vulnerability Info
This High-severity vulnerability is found in all PHP versions before 8.0.28, 8.1 before 8.1.16 and 8.2 before 8.2.3, including the End-of-Life PHP 5.6, 7.0, 7.1, 7.2, 7.3 and 7.4 release lines, which never received the upstream fix. The PHP project scores it 7.5 under CVSS 3.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H).
When open_basedir is set, PHP checks every file path against the allowed directories in php_check_specific_open_basedir(). The function resolves both the requested path and the allowed directory into stack buffers of MAXPATHLEN bytes (4096 on Linux). In PHP 7.4.33, they are declared as:
PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path)
{
char resolved_name[MAXPATHLEN];
char resolved_basedir[MAXPATHLEN];
char local_open_basedir[MAXPATHLEN];
char path_tmp[MAXPATHLEN];A resolved path can be up to MAXPATHLEN - 1 bytes long plus its terminating NUL. To compare directories, the function then appends a directory separator when the resolved path does not end with one, and writes a new terminating NUL after it:
} else {
resolved_basedir[resolved_basedir_len++] = PHP_DIR_SEPARATOR;
resolved_basedir[resolved_basedir_len] = '\0';
}If the resolved path already has the maximum length, the separator lands in the last byte of the buffer and the NUL is written one byte past its end, overwriting a byte of stack memory. The reporter found the same pattern in DOMDocument's document parser and in XMLReader::XML(), where the working directory is resolved and a slash appended. The CVE record states that this might lead to unauthorized data access or modification; HeroDevs' analysis describes a one-byte stack overwrite that can crash PHP. The reporter noted that the situation would be very exceptional.
Exploitation needs an attacker who can influence a path or working directory that resolves to exactly MAXPATHLEN - 1 bytes (4095 on Linux). HeroDevs' analysis lists the reachable paths, under any SAPI, as open_basedir checks when open_basedir is set and a checked path or allowed directory resolves to that length, and DOMDocument::loadXML(), DOMDocument::loadHTML() and XMLReader::XML() when the working directory's path has that length. Servers without open_basedir that do not use the DOM or XMLReader extensions are not exposed.
The fix enlarges the affected buffers by one byte so there is always room for the appended separator and NUL:
char resolved_name[MAXPATHLEN + 1];
char resolved_basedir[MAXPATHLEN + 1];
char local_open_basedir[MAXPATHLEN];
char path_tmp[MAXPATHLEN + 1];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.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 8.0.28, 8.1.16, 8.2.3, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- Nora Dossche (finder, remediation)