CVE-2024-4577 — PHP-CGI argument injection (pre-auth RCE)
Disclosed June 6, 2024 by Devcore (Orange Tsai's team), CVE-2024-4577 turns a Windows code-page quirk into an unauthenticated remote code execution against PHP-CGI. It was weaponised by the Akira ransomware crew within weeks of disclosure and is on CISA's KEV list. The primary attack surface is Windows; Linux is affected only in certain legacy PHP-CGI configurations.
TL;DR
- Pre-authentication RCE in PHP-CGI when running on Windows in Chinese, Japanese, or Korean locales — and on Linux only where PHP-CGI is exposed directly with
cgi.force_redirectdisabled. - CVSS 9.8 (Critical). On CISA's Known Exploited Vulnerabilities catalogue. Actively used in Akira ransomware intrusions.
- Affects PHP 8.1.x < 8.1.29, 8.2.x < 8.2.20, 8.3.x < 8.3.8. Fixed in PHP 8.1.29, 8.2.20, 8.3.8 (all released 2024-06-06).
- PHP-FPM and mod_php are not affected — the bug lives in the PHP-CGI binary's argument-parsing path.
- Mitigations beyond patching: switch from PHP-CGI to PHP-FPM, set
cgi.force_redirect = On, or add an Apache rewrite rule that rejects query strings starting with-. - Homelab relevance: bigger than the disclosure made it sound, because lazy/legacy PHP-CGI inheritances (old Docker images, XAMPP-pushed-to-VPS) are common in self-hosted PHP installs.
At a glance
| CVE ID | CVE-2024-4577 |
|---|---|
| Severity | Critical (CVSS 9.8) · KEV-listed |
| CVSS 3.1 score | 9.8 |
| CVSS vector | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-78 (OS Command Injection) — via "Best-Fit" code-page conversion in argument parsing |
| CISA KEV listed | Yes — weaponised by Akira ransomware operators shortly after disclosure |
| Fixed in | PHP 8.1.29, 8.2.20, 8.3.8 |
| Disclosed by | Devcore (Orange Tsai's team) |
| Published | 2024-06-06 |
What "Best-Fit" encoding actually is
Windows ANSI code pages include a "Best-Fit" conversion table that
maps Unicode characters which don't exist in the target code page
to visually-similar ASCII characters. The soft hyphen
(U+00AD) and several other lookalikes get mapped to a
plain ASCII - (0x2D) on the way through.
PHP-CGI filters command-line arguments that start with
-- so that an attacker can't sneak interpreter flags
in via the query string. But that filter runs before the
Windows code-page conversion. So a query string containing a soft
hyphen survives the filter, then gets rewritten into a real
- by Windows, and PHP-CGI ends up executing with
attacker-controlled flags. The same primitive applies on the rare
Linux PHP-CGI configuration that hits the equivalent code path.
Once an attacker can pass -d, they set
auto_prepend_file=php://input and POST PHP source in
the request body. PHP-CGI dutifully prepends and executes the
attacker's code with no authentication required. We're not
publishing a working payload here — the public PoCs from Devcore
and watchTowr cover that ground.
Affected configurations
The bug lives in the PHP-CGI binary, but whether it's reachable over the network depends on how PHP is wired into your web server. The matrix below is the practical "is this me?" check.
- Windows + Apache + PHP-CGI in CJK locales (Chinese / Japanese / Korean code pages): vulnerable. This is the primary attack surface and what every public exploit targets.
- Linux + PHP-CGI exposed directly +
cgi.force_redirect = Off: vulnerable. Rare in modern stacks; common in legacy hand-rolled setups, old Docker images, and any "I copied my dev XAMPP layout to a VPS" arrangement. - PHP-FPM (any OS): not affected. Different binary, different argument-handling path — this is the recommended deployment shape and has been for years.
- mod_php (Apache module): not affected. There's no CGI argument-parsing step to abuse.
- CLI usage (
php script.php): not exploitable over the network. The bug needs an HTTP request reaching PHP-CGI's argv pathway.
Affected versions and fix paths
| PHP branch | Vulnerable | Fixed in |
|---|---|---|
| PHP 8.1.x | ≤ 8.1.28 | 8.1.29 |
| PHP 8.2.x | ≤ 8.2.19 | 8.2.20 |
| PHP 8.3.x | ≤ 8.3.7 | 8.3.8 |
| PHP 7.x and earlier | End-of-life — no official fix | Manual backport, distro-vendor patch, or migrate to 8.x |
Long-term support distros backport the fix into older PHP
packages under the original version number — for example,
Debian 12's php8.2 package gets the security patch
applied while keeping the 8.2.7 base. If your distro tracks LTS,
apt upgrade or dnf upgrade is enough;
the package version string won't jump to 8.2.20 but the patch
will be present.
Quick scan check
Run these on each host to figure out (a) what PHP version is installed and (b) which SAPI is actually serving requests. The SAPI matters more than the version — PHP-FPM hosts are not exposed regardless of patch level.
php -v
php-cgi -v 2>/dev/null
# Which SAPI is in use? Look for FPM/FastCGI vs CGI/FastCGI.
php -i | grep -i "Server API"
# Is the php-cgi binary actually installed?
dpkg -l 'php*-cgi' 2>/dev/null # Debian / Ubuntu
rpm -qa 'php*-cgi' 2>/dev/null # RHEL / Alma / Rocky
# Is cgi.force_redirect on? (Off = vulnerable when PHP-CGI is exposed)
grep -r "cgi.force_redirect" /etc/php* 2>/dev/null
If Server API reads FPM/FastCGI on every
host, you're not exposed by this CVE no matter what the version
string says. If you see CGI/FastCGI and the
php-cgi binary is reachable from the web server,
that's the configuration that needs patching.
Mitigations beyond patching
- Switch from PHP-CGI to PHP-FPM. This is the recommended deployment shape for modern PHP and removes the vulnerable code path entirely. It's also faster and easier to monitor.
- Set
cgi.force_redirect = Oninphp.ini. This prevents PHP-CGI from being invoked directly via HTTP and breaks the attack precondition. - Apache rewrite rule rejecting query strings starting with
-— the Devcore advisory provides the exactRewriteCond/RewriteRulepair. Useful as belt-and-braces in front of an unpatched stack. - Don't run PHP-CGI on Windows handling untrusted input. Even after patching, the combination is brittle and historically attacker-friendly.
- Front-load with a reverse proxy that drops requests containing suspicious query-string prefixes — see before you expose a service to the web for the broader checklist.
Why this is more relevant in homelabs than the disclosure suggested
The initial disclosure framed CVE-2024-4577 as a Windows-CJK-locale curiosity, which made many Linux-shop sysadmins skim past it. In practice the affected configuration shows up regularly in self-hosted setups:
- Old Docker images that still use PHP-CGI behind Apache because the maintainer never updated the base image.
- XAMPP-style "everything bundled" setups copied from a developer's laptop onto a public VPS, where
cgi.force_redirectdefaults haven't been hardened. - Legacy Mediawiki / Roundcube / phpMyAdmin installs that were stood up against PHP-CGI a decade ago and never re-platformed onto PHP-FPM.
- Cheap shared-hosting control panels that still drive PHP via CGI for per-user isolation.
The Akira ransomware crew weaponised this within weeks of disclosure, specifically against small-to-mid public-facing PHP installations — exactly the shape of a one-or-two-VPS homelab that serves a Nextcloud or a personal wiki. If you've got a "set it up in 2018 and forgot about it" PHP box, this is the CVE to triage first. The triaging CVE findings guide walks through the order of operations.
The wider pattern — long-lived self-hosted services drifting out of patch coverage — is covered in the patching gap in self-hosted services.
What Noxen does about this
Noxen's package-inventory probe records the installed PHP
package versions on every enrolled Linux host, then matches them
against CVE-2024-4577 from the signed daily feed. The match is
informational: Noxen can tell you the host has an
affected PHP version installed, but the network-side
exploitability also depends on the SAPI (PHP-FPM vs PHP-CGI),
cgi.force_redirect, and (on Windows) the system
locale — settings Noxen doesn't probe today.
Patch the package and the underlying primitive is gone; that's
the action Noxen drives you toward. Pair the finding with the
php -i | grep "Server API" check above to confirm
whether the host was ever actually reachable.
Authoritative sources
- NVD entry for CVE-2024-4577
- cve.org record
- FIRST EPSS API for CVE-2024-4577
- CISA KEV catalogue (search for CVE-2024-4577)
- PHP 8.x ChangeLog (8.1.29 / 8.2.20 / 8.3.8 entries)
See what Noxen does about CVEs like this → More on CVE management →