On August 7, 2019, Juniper Threat Labs started seeing attacks on PHP-FPM (FastCGI Process Manager) on port 9000. This attack works by passing PHP configuration options that allows injection of a PHP script to a listening PHP-FPM service. The attack payload is a base64 encoded PHP script that collects system information, presumably as part of a reconnaissance stage.
What is PHP-FPM?
PHP-FPM is a method to execute PHP in modern environments. It is an alternative to the FastCGI daemon for PHP, commonly used in conjunction with web servers like Apache or NginX to handle high loads of PHP requests. A daemon listens for incoming connections so that PHP doesn't need to be started for each request. The web server will forward PHP script execution requests to FPM. It can run either on a file socket or on a TCP port. By default, it listens on TCP port 9000 and should only listen on the localhost.
How does the attack work?
During our research on this attack, we discovered someone has already described this attack and posted it on openwall on July 27, 2019. The person also published a POC to show how the attack would work. Our telemetry does not indicate any actual attack in the wild using this technique at that time.
The PHP-FPM daemon supports passing PHP configuration options via the PHP_VALUE variable. This can be used to inject PHP code via the auto_prepend_file configuration option, which is basically an option to provide a script that will be prepended to every other script on the target system for execution. This may be prevented by disabling settings for allow_url_include or allow_url_fopen but, unfortunately, these settings can be changed with PHP_VALUE as well, overriding the default settings. The only thing an attacker needs is a PHP or a phar file on the target systems where the injected PHP script will be prepended and executed.
The attack uses FastCGI protocol to communicate directly with the PHP-FPM daemon. It passes PHP_VALUE variables necessary to prepend and execute a PHP script that is base64 encoded. So far, the attack we have seen is coming from IP 220.127.116.11
The injected PHP script collects system information, including:
Current User information
Host File Information
Network Related information
/etc/passwd and /etc/shadow
It achieves shell execution by taking advantage of PHP functions that allow shell command execution, such as:
It is important to note that the remote code execution could only work if the PHP-FPM service is exposed beyond the local host, either to the internet or to internal hosts that would allow lateral movement. At this point, we don’t know yet how many PHP-FPM services are exposed to the internet. Our advice is to check and make sure that your PHP-FPM is properly configured. By default, it is an internal ONLY protocol and it should only listen to localhost.