|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79980 require_once can include a file twice via symlink loops
Submitted: 2020-08-16 05:18 UTC Modified: 2021-03-09 14:26 UTC
Avg. Score:4.0 ± 1.0
Reproduced:1 of 3 (33.3%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: i at littlefisher dot me Assigned: cmb (profile)
Status: Wont fix Package: *Directory/Filesystem functions
PHP Version: 7.2.33 OS: Ubuntu18.04
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Bug Type:
From: i at littlefisher dot me
New email:
PHP Version: OS:


 [2020-08-16 05:18 UTC] i at littlefisher dot me
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`.



Test script:
/* index.php */
if(isset($_GET['content'])) {
    $content = $_GET['content'];
/* config.php */
$MYSQL_PORT = 3306;
$MYSQL_USERNAME = 'admin';
$MYSQL_PASSWORD = 'admin';

Expected result:
Excepted result is `config.php` cannot be included twice by the recursive symbollink.


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2021-03-09 14:26 UTC]
-Status: Open +Status: Wont fix -Assigned To: +Assigned To: cmb
 [2021-03-09 14:26 UTC]
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.
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Jul 25 08:01:30 2024 UTC