[php-src] Issue #21971: Harden open_basedir restrictions in various extensions

[email protected] (LamentXU123)
Newsgroups php.bugs
Message-ID <[email protected]>
Issue: https://github.com/php/php-src/issues/21971
Author: LamentXU123

### Description

Now, several extensions in the php codebase has functions with the ability to read/write outside the open_basedir restrictions. While they all requires some level of file 

That is because, the open_basedir restrictions only works on PHP streams, and some of our extensions read/write without it, and therefore bypassing the open_basedir check.

Examples found while auditing similar `open_basedir` behavior:

* `ext/dba`: non-stream DBA handlers such as `gdbm`, `qdbm`, or `lmdb` open paths through their backend libraries, e.g. `gdbm_open()`, `dpopen()`, `mdb_env_open()`.
* `ext/gettext`: `bindtextdomain()` resolves a directory and then passes it to libc/gettext, which later loads `.mo` files from that location.
* `ext/openssl`: SSL context options such as `cafile`, `capath`, and `dh_param` may be passed to OpenSSL APIs such as `SSL_CTX_load_verify_locations()` or `BIO_new_file()`.
* `ext/gd`: FreeType font loading can pass the resolved font path to `FT_New_Face()` after locating it with `access()`.

IMO, all of them are supposed to be fixed, that they should align with the expected open_basedir behavior. I know that the above only work with conditions (e.g. know dba keys for dpopen, or being a .mo file for bindtextdomain) but all of them should only works under the restrictions of open_basedir due to serious safety concerns. Which is simply by adding

```c
#include "main/fopen_wrappers.h"

if (php_check_open_basedir(path)) {
    RETURN_FALSE;
}

/* then call native/library open */
```

I don't think this requires a RFC so I would like to directly open this issue to discuss about this. cc @iluuu1994 . Thanks!

Below are some example payloads:

```
<?php
ini_set('open_basedir', __DIR__ . '/allowed');

$db = dba_open('/tmp/outside.gdbm', 'r', 'gdbm');
var_dump(dba_fetch('secret', $db));
```
and
```php
<?php
ini_set('open_basedir', __DIR__ . '/allowed');

bindtextdomain('leak', '/tmp/outside-locale');
textdomain('leak');

echo gettext('secret_key'), "\n";
```
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.