CVE-2020-7070
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 Security Bypass vulnerability (CVE-2020-7070) has been identified in the way PHP parses the Cookie request header into $_COOKIE, which allows an attacker who can set an ordinary cookie in a victim's browser, for example from a sibling subdomain or over plain HTTP, to have PHP present it to the application as a __Host- or __Secure- cookie. PHP tracks this issue as bug #79699.
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 7.2.34, PHP 7.3 before 7.3.23 and PHP 7.4 before 7.4.11, 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(main/php_variables.c) - Affected versions: <7.2.34, >=7.3.0 <7.3.23, >=7.4.0 <7.4.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.2.34, 7.3.23, 7.4.11
- NES for PHP 5.6.1 (based on PHP 5.6.40)
Vulnerability Info
This Medium-severity vulnerability is found in the request variable parser of all PHP versions before 7.2.34, 7.3 before 7.3.23 and 7.4 before 7.4.11, 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 4.3 under CVSS 3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N).
Browsers give special treatment to cookies whose names start with __Secure- or __Host-. A __Secure- cookie is accepted only if it was set with the Secure flag from an HTTPS page, and a __Host- cookie must in addition have no Domain attribute and the path /, so a sibling subdomain cannot set it. Applications rely on these prefixes to know that a cookie came from their own origin over HTTPS. PHP, however, URL-decodes cookie names as well as values when it builds $_COOKIE. In PHP 5.6.40, php_default_treat_data() does this for each cookie:
*val++ = '\0';
php_url_decode(var, strlen(var));
val_len = php_url_decode(val, strlen(val));
val = estrndup(val, val_len);The browser does not apply the prefix rules to a name such as __%48ost-session, because it does not start with __Host-, so any page that can set cookies for the domain, including a sibling subdomain or a plain-HTTP response, can set it. PHP decodes %48 to H and hands the cookie to the application as $_COOKIE['__Host-session']. The CVE record notes that this can let an attacker forge a cookie that is supposed to be secure, and refers to CVE-2020-8184, the same issue in Ruby's Rack.
Exploitation needs an application that trusts __Host- or __Secure- cookies, for example for session or CSRF tokens, and an attacker who can set cookies for the victim's domain, such as through a compromised or user-controlled subdomain or a network position on plain HTTP. The victim's browser must then visit the application. The issue affects any SAPI that serves HTTP. Applications that do not rely on these prefixes are not affected.
The fix stops URL-decoding cookie names; values are still decoded. As with the upstream fix, this changes behavior: a cookie whose name contains % escapes keeps them in $_COOKIE. The fixed code reads:
*val++ = '\0';
if (arg != PARSE_COOKIE) {
php_url_decode(var, strlen(var));
}
val_len = php_url_decode(val, strlen(val));
val = estrndup(val, val_len);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.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 7.2.34, 7.3.23, 7.4.11, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- fletchto99 (finder)
- Stanislav Malyshev (remediation)