Attack scenariosPHP vulnerability
PHP-CGI argument injection on Windows
One character in the query string turns into PHP command-line options. An unauthenticated attacker then runs code on the server.
The problem
When PHP runs as CGI, the web server passes parts of the request to the php-cgi binary. In 2012 a query string such as ?-s already became a command-line option (CVE-2012-1823), and PHP added a check that rejects a query string starting with a hyphen.
On Windows the command line is converted to the system code page. With the Best-Fit conversion of some code pages, the soft hyphen (byte 0xAD) becomes an ordinary hyphen. Apache does not escape it, so the old check does not see an option while php-cgi receives one. A single request turns on allow_url_include, feeds PHP a script through php://input and runs it.
PHP 5, 7 and 8.0 are past end of life and will not get a fix. Public exploits appeared within days of disclosure and were used to deliver ransomware and botnet malware.
Attack request
The body below only prints a marker, so the request is safe to replay against your own test application.
Request
POST /index.php?%ADd+allow_url_include%3D1+%ADd+auto_prepend_file%3Dphp://input HTTP/1.1
Host: app.example.com
Content-Type: application/x-www-form-urlencoded
<?php echo "mikiri-test"; ?>
What Mikiri WAF detects
Filter decodes the query string before it is checked, and each of these signals blocks the request on its own:
- Soft hyphen before a PHP option. The Best-Fit byte
%ADor the UTF-8 sequence%C2%AD, followed by a-doption such asallow_url_includeorauto_prepend_file=php://input. - The original form. The same options with an ordinary hyphen, as in
CVE-2012-1823. - Direct call to the PHP binary. A request to
/php-cgi/php-cgi.exe, the path that XAMPP for Windows exposes by default.
These rules are virtual patches. They arrive with signature updates in both plans. A virtual patch can block the known exploit pattern at the WAF layer across protected hosts, reducing exposure while the affected PHP runtime is updated. Validate the rule against relevant request variants in a controlled test environment.
What you see in WMC
The blocked request appears under the host in Attacks. The record shows the method, the path and the query string, the zone where the rule matched, the rule and its description, and the mark that the request was blocked. The request never reaches PHP.
Expected result
- Response403 from Filter
- Zonequery
- BackendRequest not forwarded
Reproduce it
Send the request above to a test application behind Mikiri WAF, with or without PHP installed. Then open the record in Attacks. To record the attack without blocking it, switch the host to detection mode first: the record is then marked as detected but not blocked.
Replay it on your own traffic
Deploy Mikiri WAF on premises and run this request against your applications. Evaluation is free, and application traffic stays on premises.
