CVE-2024-5458
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 filter extension validates untrusted input, and filter_var() with FILTER_VALIDATE_URL is the standard way for PHP applications to check that a string is a well-formed URL.
An Improper Input Validation vulnerability (CVE-2024-5458) has been identified in the FILTER_VALIDATE_URL filter of PHP's filter extension, which allows an attacker to get a URL with invalid user information (the user name and password part) accepted as valid when its host is a bracketed IPv6 address, so that code relying on the check may later parse or use the URL differently. PHP tracks this issue as GHSA-w8qr-v226-r27w.
Per MITRE CWE-20: The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.
This issue affects all versions of PHP before 8.1.29, PHP 8.2 before 8.2.20 and PHP 8.3 before 8.3.8, which includes every End-of-Life release line from PHP 5.6 through 8.0, each up to its final release.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/filter) - Affected versions: <8.1.29, >=8.2.0 <8.2.20, >=8.3.0 <8.3.8
- 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.29, 8.2.20, 8.3.8
- 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 Medium-severity vulnerability is found in the filter extension of all PHP versions before 8.1.29, 8.2 before 8.2.20 and 8.3 before 8.3.8, including every End-of-Life release line from PHP 5.6 through 8.0, which never received the upstream fix. The PHP project scores it 5.3 under CVSS 3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N).
For http and https URLs, php_filter_validate_url() checks the host and then, since the fix for CVE-2020-7071, checks that the user name and password contain only characters RFC 3986 allows. In PHP 7.4.33, the host check reads:
/* An IPv6 enclosed by square brackets is a valid hostname */
if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2, NULL)) {
php_url_free(url);
return;
}
// Validate domain
if (!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)) {
php_url_free(url);
RETURN_VALIDATION_FAILED
}When the host is a valid bracketed IPv6 address, the function returns success at once and never reaches the user information check that follows. A URL whose user information contains a forbidden character, such as the opening square bracket the reporter used, is rejected with an IPv4 or domain host but accepted with an IPv6 host. The advisory describes this as the same problem as CVE-2020-7071 for IPv6 hosts. On PHP 5.6, 7.2 and 7.4 before 7.4.15, which predate the CVE-2020-7071 fix, user information was not checked for any host; the NES for PHP releases include both fixes.
Exploitation needs an application that validates an attacker-supplied URL with FILTER_VALIDATE_URL and then relies on that result, for example before fetching the URL, redirecting to it or parsing it with another component, under any server API. The attacker gets a malformed URL past validation, which another parser may interpret differently; the record's impact is limited to integrity. Applications that do not use FILTER_VALIDATE_URL as a security check are not exposed.
The fix moves the IPv6 test into a helper and treats it as one of two acceptable host forms, so validation continues to the user information check whatever the host. On PHP 5.6, HeroDevs' analysis notes that the backport also checks http(s) hosts with the shared domain and IPv6 validators, so a bracketed IPv6 host is now accepted and an invalid domain label rejected. The fixed check reads:
if (
/* An IPv6 enclosed by square brackets is a valid hostname.*/
!php_filter_is_valid_ipv6_hostname(s, l) &&
/* Validate domain.
* This includes a loose check for an IPv4 address. */
!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)
) {
php_url_free(url);
RETURN_VALIDATION_FAILED
}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.29, 8.2.20, 8.3.8, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- c01l (finder)
- Nora Dossche (remediation)