Harden open_basedir restrictions in various extensions (or even deprecate open_basedir)
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- C
- Sterne
- 40.4k
- Forks
- 8.1k
- Ø Merge
- 2 T. 13 Std.
- Gemergte PRs (30 T.)
- 96
Beschreibung
Description
Now, several extensions in the php codebase has functions with the ability to read/write outside the open_basedir restrictions.
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 asgdbm,qdbm, orlmdbopen 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.mofiles from that location.ext/openssl: SSL context options such ascafile,capath, anddh_parammay be passed to OpenSSL APIs such asSSL_CTX_load_verify_locations()orBIO_new_file().ext/gd: FreeType font loading can pass the resolved font path toFT_New_Face()after locating it withaccess().ext/standard:stream_resolve_include_path
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
#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
ini_set('open_basedir', __DIR__ . '/allowed');
bindtextdomain('leak', '/tmp/outside-locale');
textdomain('leak');
echo gettext('secret_key'), "\n";
and (this can only check if a file exists, but without any restrictions)
<?php
ini_set('open_basedir', __DIR__ . '/allowed');
ini_set('include_path', '/etc');
var_dump(stream_resolve_include_path('passwd'));
var_dump(@file_get_contents('passwd', use_include_path: true));
I don't sure if we should treat this as a security issue :) This research is done with @q1uf3ng
TL;DR some of the functions use zend_resolve_path for file IO, the API doesn't check if it fits in the open_basedir restrictions.
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginnen Sie mit dem Lesen von main/fopen_wrappers.h und überprüfen Sie die in ext/dba, ext/gettext, ext/openssl, ext/gd und ext/standard genannten Aufrufstellen auf nativen Dateizugriff. Verwenden Sie die bereitgestellten Beispiele für DBA, gettext und stream_resolve_include_path als Reproduktionen. Die Aufgabe ist abgeschlossen, wenn die betroffenen Funktionen Einschränkungen durch open_basedir konsistent berücksichtigen und eine Regressionstestabdeckung für die demonstrierten Pfade vorhanden ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- c, php
- Bereich
- security
- Issue-Typ
- Bug
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Ruhig
- Klarheit
- Muss geklärt werden
- Anfängerfreundlichkeit
- 35/100