CVE-2024-8927
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 CGI SAPI, the php-cgi binary, lets a web server run PHP scripts as CGI programs.
A Security Bypass vulnerability (CVE-2024-8927) has been identified in the cgi.force_redirect check of PHP's CGI SAPI, which allows a remote attacker to bypass the protection against calling php-cgi directly by sending a Redirect-Status request header, which in some configurations can lead to arbitrary file inclusion. PHP tracks this issue as GHSA-94p6-54jq-9mwp.
Per MITRE CWE-1220: The product implements access controls via a policy or other feature with the intention to disable or restrict accesses (reads and/or writes) to assets in a system from untrusted agents. However, implemented access controls lack required granularity, which renders the control policy too broad because it allows accesses from unauthorized agents to the security-sensitive assets.
This issue affects all versions of PHP before 8.1.30, PHP 8.2 before 8.2.24 and PHP 8.3 before 8.3.12, which includes every release of the End-of-Life PHP 5.6, 7.0 through 7.4 and 8.0 release lines.
Details
Module Info
- Product: PHP
- Affected packages:
php-src(sapi/cgi) - Affected versions: <8.1.30, >=8.2.0 <8.2.24, >=8.3.0 <8.3.12
- 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.30, 8.2.24, 8.3.12
- 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 the CGI SAPI of all versions of PHP before 8.1.30, PHP 8.2 before 8.2.24 and PHP 8.3 before 8.3.12, including the End-of-Life PHP 5.6, 7.0 through 7.4 and 8.0 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:L/PR:N/UI:N/S:U/C:H/I:N/A:N).
When cgi.force_redirect is on, which is the default, php-cgi refuses to run unless the web server shows that it redirected the request to PHP, rather than a client calling the binary directly. Apache signals this with the REDIRECT_STATUS environment variable. Older code also accepted HTTP_REDIRECT_STATUS, which the comment attributes to Netscape and a module called redirect.so. In PHP 7.4.33 the check reads:
if (!getenv("REDIRECT_STATUS") &&
!getenv ("HTTP_REDIRECT_STATUS") &&
/* this is to allow a different env var to be configured
* in case some server does something different than above */
(!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
) {Under the CGI convention, a web server passes each request header to the program as an HTTP_* environment variable. A client that sends a Redirect-Status: header therefore sets HTTP_REDIRECT_STATUS itself, and the check passes for a request sent straight to php-cgi. The guard that cgi.force_redirect is meant to provide is lost, and according to the advisory this can lead to arbitrary file inclusion in some configurations. Setting cgi.redirect_status_env did not help, because the hard-coded names were accepted first.
Exploitation needs php-cgi run as a CGI program by a web server that passes request headers as HTTP_* variables, with cgi.force_redirect on. HeroDevs' analysis notes that the php CLI binary, the Apache module and php-fpm do not use this check (php-fpm's copy of the code is never reached), so deployments using them are not affected.
The fix checks the variable named by cgi.redirect_status_env first, falls back to REDIRECT_STATUS only, and no longer accepts HTTP_REDIRECT_STATUS:
const char *redirect_status_env = CGIG(redirect_status_env);
if (!redirect_status_env) {
/* Apache will generate REDIRECT_STATUS. */
redirect_status_env = "REDIRECT_STATUS";
}
if (!getenv(redirect_status_env)) {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.
Until an upgrade is possible, run PHP through PHP-FPM or the Apache module instead of php-cgi, or make sure php-cgi cannot be reached directly through the web server.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 8.1.30, 8.2.24, 8.3.12, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- Owen Gong (finder)
- RyotaK (finder)
- Nora Dossche (remediation)