Nginx + PHP 7 Remote Code Execution Vulnerability

On October 24th2019, PHP released updates to address a remote code execution vulnerability. The vulnerability allows an attacker to run arbitrary commands on a vulnerable server by a specially crafted URL. This issue is tracked with CVE-2019-11043.

Vulnerability Analysis:

The vulnerability resides in the “env_path_info” underflow in PHP-FPM . It contains pointer arithmetics that assumes that env_path_info has a prefix equal to the path to the php script. However, the code does not check this assumption is satisfied. The absence of the check can lead to an invalid pointer in the “path_info” variable.

Such conditions can be achieved in a pretty standard Nginx configuration. If one has Nginx config as below:

location ~ [^/]\.php(/|$) {

fastcgi_split_path_info ^(.+?\.php)(/.*)$;

fastcgi_param PATH_INFO       $fastcgi_path_info;

fastcgi_pass   php:9000;

The regexp in `fastcgi_split_path_info` directive can be broken using the newline character (in encoded form, %0a). Broken regexp leads to empty PATH_INFO, which triggers the bug.

Pre-conditions To Exploit this Vulnerability:

  1. Nginx + php-fpm, location ~ [^/]\.php(/|$) must be forwarded to php-fpm (maybe the regexp can be stricter, see #1).
  2. The fastcgi_split_path_info directive must be there and contain a regexp starting with ^ and ending with $, so we can break it with a newline character.
  3. There must be a PATH_INFO variable assignment via statement fastcgi_param PATH_INFO $fastcgi_path_info;. At first, we thought it is always present in the fastcgi_params file, but it’s not true.
  4. No file existence checks like try_files $uri =404 or if (-f $uri). If Nginx drops requests to non-existing scripts before FastCGI forwarding, our requests never reach php-fpm. Adding this is also the easiest way to patch.

Exploit:

A proof-of-concept to exploit this vulnerability was released on GitHub. It also includes a docker image to reproduce the vulnerability.

Command Execution:

The figure below shows ‘ls’ command execution on a vulnerable server

Mitigations:

PHP released updated versions 7.3.11, 7.2..24 and 7.1.33 to fix this vulnerability. A possible workaround is to check if a script file exists. This can be done using the ‘try_files’ directive or ‘if (-f $uri).’

Qualys customers can scan their network with QID:87400 to detect vulnerable assets. Kindly continue to follow on Qualys Threat Protection for more coverage on vulnerabilities.

Leave a Reply

Your email address will not be published. Required fields are marked *