CVE-2024-8932
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 ldap extension connects PHP applications to LDAP directory servers, and its ldap_escape() function escapes values before they are placed in LDAP filters or distinguished names.
A Buffer Overflow vulnerability (CVE-2024-8932) has been identified in the ldap_escape() function of PHP's ldap extension, which allows an attacker who can pass a very long string to ldap_escape() on a 32-bit build of PHP to make the computed output length wrap around, so that PHP writes the escaped string past the end of a buffer that is too small. PHP tracks this issue as GHSA-g665-fm4p-vhff.
Per MITRE CWE-787: The product writes data past the end, or before the beginning, of the intended buffer.
This issue affects PHP 5.6.0 through 8.1.30, PHP 8.2 before 8.2.26 and PHP 8.3 before 8.3.14, when PHP is built for a 32-bit platform.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/ldap) - Affected versions: >=5.6.0 <8.1.31, >=8.2.0 <8.2.26, >=8.3.0 <8.3.14 (32-bit builds)
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 8.1.31, 8.2.26, 8.3.14
- 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 Critical-severity vulnerability is found in the ldap extension of PHP 5.6.0 through 8.1.30, PHP 8.2 before 8.2.26 and 8.3 before 8.3.14 on 32-bit systems, including the End-of-Life PHP 5.6, 7.0, 7.1, 7.2, 7.3, 7.4 and 8.0 release lines, which never received the upstream fix. The PHP project scores it 9.8 under CVSS 3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H).
ldap_escape() replaces each special character in a value with a backslash and two hex digits. It first adds up the length of the output, three bytes for each escaped character and one for every other byte, allocates a string of that size, and then writes the escaped value into it. In PHP 7.4.33 the length calculation reads:
for (i = 0; i < valuelen; i++) {
len += (map[(unsigned char) value[i]]) ? 3 : 1;
}
/* Per RFC 4514, a leading and trailing space must be escaped */
if ((flags & PHP_LDAP_ESCAPE_DN) && (value[0] == ' ')) {
len += 2;
}
if ((flags & PHP_LDAP_ESCAPE_DN) && ((valuelen > 1) && (value[valuelen - 1] == ' '))) {
len += 2;
}
ret = zend_string_alloc(len, 0);Nothing checks len for overflow. On a 32-bit system, where size_t holds at most about 4 GiB, an input of about 1.4 GiB made of characters that need escaping produces a length that wraps around to a small number. PHP allocates a buffer of that small size, and the loop that follows writes the full escaped value past its end, corrupting the heap. The CVE record classifies this as an out-of-bounds write.
Exploitation needs a 32-bit build of PHP with the ldap extension, an application that passes attacker-controlled input to ldap_escape(), and a memory_limit (and, for request data, a post_max_size) large enough to hold a string of that size, which common settings do not allow. It works in any SAPI. 64-bit builds are not affected by the overflow; HeroDevs' analysis found that on 64-bit PHP 5.6 the oversized allocation already ended the request with a fatal error.
The fix checks every step of the length calculation against the largest possible string size and makes ldap_escape() fail instead of allocating a short buffer. In PHP 8.1.31 the loop reads:
for (i = 0; i < valuelen; i++) {
size_t addend = (map[(unsigned char) value[i]]) ? 3 : 1;
if (len > ZSTR_MAX_LEN - addend) {
return NULL;
}
len += addend;
}Upstream reports the failure as a ValueError. PHP 7.4 has no such exception type, so NES for PHP 7.4 throws an Exception for an over-long input; the NES for PHP 5.6 fix likewise throws a catchable exception.
Mitigation
The PHP project publishes security fixes only for its supported release lines. PHP 5.6, 7.0, 7.1, 7.2, 7.3, 7.4 and 8.0 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.1.31, 8.2.26, 8.3.14, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- Yiheng Cao (finder)
- Nora Dossche (remediation)