CVE-2020-7066
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 get_headers() function sends an HTTP request to a URL and returns the response headers.
A Server-Side Request Forgery (SSRF) vulnerability (CVE-2020-7066) has been identified in the get_headers() function of PHP's standard library, which allows an attacker who controls a URL that an application checks and then passes to get_headers() to make the application send the request to a different host than the one it checked. PHP tracks this issue as bug #79329.
Per MITRE CWE-918: The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
This issue affects PHP before 7.2.29, PHP 7.3 before 7.3.16 and PHP 7.4 before 7.4.4, 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(ext/standard) - Affected versions: <7.2.29, >=7.3.0 <7.3.16, >=7.4.0 <7.4.4
- 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.29, 7.3.16, 7.4.4
- NES for PHP 5.6.1 (based on PHP 5.6.40)
Vulnerability Info
This Medium-severity vulnerability is found in the standard library of PHP before 7.2.29, 7.3 before 7.3.16 and 7.4 before 7.4.4. The CVE record does not list PHP 5.6, 7.0 or 7.1, but HeroDevs' analysis found the same behavior in the End-of-Life PHP 5.6, 7.0 and 7.1 release lines, which never received the 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:L/I:N/A:N). The record classifies it as CWE-170, Improper Null Termination.
PHP strings can contain NUL bytes, but get_headers() accepted its URL argument as a plain string and passed it to the stream layer, which treats it as a C string that ends at the first NUL byte. Everything after a NUL byte was silently ignored. Functions such as parse_url(), which an application may use to check the URL first, see the whole string.
The reporter showed the consequence with a URL such as http://localhost\0.example.com: parse_url() reports a host ending in .example.com, so an application that only allows hosts under that domain accepts it, but get_headers() requests http://localhost. The CVE record notes that software may then make incorrect assumptions about the target and send information to the wrong server, and the response headers returned to the application may come from a host the attacker chose.
Exploitation needs an application that calls get_headers() on a URL the attacker influences after validating it with string functions. This applies to any SAPI. Applications that never pass user-supplied URLs to get_headers() are not exposed.
The fix declares the URL as a path parameter, which PHP rejects when it contains a NUL byte, so get_headers() fails with the warning "expects parameter 1 to be a valid path" instead of fetching a truncated URL. In the upstream PHP 7 code, the parameter parsing now reads:
ZEND_PARSE_PARAMETERS_START(1, 3)
Z_PARAM_PATH(url, url_len)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(format)
Z_PARAM_RESOURCE_EX(zcontext, 1, 0)
ZEND_PARSE_PARAMETERS_END();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.29, 7.3.16, 7.4.4, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- 64796c6e69 (finder)
- Stanislav Malyshev (remediation)