W3docs

chroot()

Scopri come la funzione chroot() di PHP cambia la directory radice del processo, con sintassi, esempi e limitazioni.

Funzione PHP chroot()

La funzione chroot() cambia la directory radice del processo in esecuzione nella directory specificata, portando poi la directory di lavoro corrente a /. Dopo la chiamata, il processo non può più vedere né raggiungere alcun file al di sopra della nuova radice — è "rinchiuso" all'interno di quell'albero di directory. Questa tecnica è comunemente chiamata chroot jail.

Questa pagina spiega cosa fa chroot(), quando utilizzarla (e quando non farlo), la sua sintassi e le limitazioni da conoscere prima di affidarsi ad essa.

Sintassi

chroot(string $directory): bool
ParametroDescrizione
$directoryIl percorso della directory che diventa la nuova radice (/) del processo.

Valore restituito: true in caso di successo, false in caso di errore.

Requisiti

chroot() non è disponibile ovunque. Prima di utilizzarla, tieni presenti questi vincoli:

  • Funziona solo con CLI e CGI SAPI — non è disponibile per la maggior parte dei module SAPI come mod_php o PHP-FPM durante una normale richiesta web.
  • Non è implementata su Windows.
  • Il processo chiamante deve avere privilegi di root (superutente). Un utente normale non può cambiare la directory radice.

A causa di questi requisiti, chroot() viene utilizzata principalmente in daemon CLI PHP a lunga esecuzione e script worker, non nel codice che gestisce le normali richieste HTTP.

Esempio Base

Questo script rinchiude il processo in /var/www/jail, poi legge un percorso relativo alla nuova radice:

<?php
// Must be run as root, on CLI.
if (chroot('/var/www/jail')) {
    echo "Root directory changed.\n";

    // Paths are now relative to /var/www/jail.
    // What was /var/www/jail/data/config.txt is now /data/config.txt
    $contents = file_get_contents('/data/config.txt');
    echo $contents;
} else {
    echo "Failed to change root directory.\n";
}

Dopo la chiamata a chroot(), il percorso /data/config.txt fa riferimento in realtà a /var/www/jail/data/config.txt sul filesystem reale. Il processo semplicemente non può costruire un percorso che esca dalla jail.

Confermare la Directory di Lavoro

Poiché chroot() sposta anche la directory di lavoro a /, puoi confermare il cambiamento con getcwd():

<?php
chroot('/var/www/jail');

echo getcwd();   // "/"  (which is /var/www/jail on the real filesystem)

Se hai bisogno di una directory di lavoro diversa all'interno della jail, impostala esplicitamente con chdir() dopo la chiamata a chroot().

Perché Usare chroot()

Lo scopo di chroot() è l'isolamento. Una volta che un processo è nella jail:

  • Non può aprire, leggere o scrivere file al di fuori della nuova radice, nemmeno con percorsi assoluti.
  • Un bug o un exploit che tenta il directory traversal (../../etc/passwd) non ha nulla da attraversare — non esiste alcun percorso sopra /.
  • Puoi fornire un albero di directory minimale (solo i file di cui il worker ha effettivamente bisogno), riducendo la superficie di attacco.

Un pattern comune consiste nell'avviare un daemon come root, chiamare chroot() per confinarlo in una sandbox, e poi abbassare i privilegi con posix_setuid() / posix_setgid() in modo che il processo nella jail non giri più come root.

chroot() vs open_basedir

Questi due meccanismi vengono spesso confusi. Risolvono un problema simile a livelli molto diversi:

chroot()open_basedir
LivelloRadice del processo a livello di sistema operativoControllo del percorso nel motore PHP
Dove si impostaNel codice a runtimephp.ini, .htaccess, pool FPM
Funziona con web SAPINo (solo CLI/CGI)
Richiede privilegi di rootNo
RobustezzaJail imposta dal sistema operativoIndicativa, può essere indebolita dai symlink

Se devi solo mantenere una normale richiesta web all'interno di una directory, open_basedir è lo strumento pratico da usare. Usa chroot() quando gestisci un processo CLI e vuoi un vero confine a livello di sistema operativo.

Limitazioni e Avvertenze

  • Non è un confine di sicurezza perfetto. Un processo che gira ancora come root all'interno di un chroot può spesso fuggire. Abbassa sempre i privilegi dopo aver applicato la jail.
  • Dipendenze mancanti. La jail non ha /lib, /etc, /usr a meno che non li inserisca tu. Le funzioni che dipendono da file di sistema (lookup DNS, dati di localizzazione, fusi orari, librerie dinamiche) potrebbero fallire all'interno della jail.
  • Irreversibile per il processo. Non esiste un unchroot(); il cambiamento dura per tutta la vita del processo.
  • Dipende dall'ambiente. Poiché la disponibilità dipende dal SAPI e dal sistema operativo, proteggi le chiamate e verifica il valore restituito invece di dare per scontato il successo.

Conclusione

chroot() confina un processo PHP in un singolo albero di directory cambiando la sua radice in quella directory e reimpostando la directory di lavoro su /. È un potente strumento di isolamento a livello di sistema operativo per i daemon CLI privilegiati, ma richiede i permessi di root, è limitato a CLI/CGI e non è disponibile su Windows. Per le restrizioni per singola richiesta in un normale stack web, usa invece open_basedir e tratta chroot() come uno strato di una strategia di difesa in profondità. Per saperne di più sul lavoro con i percorsi e il filesystem, consulta chdir(), getcwd() e il capitolo sul filesystem PHP.

Diagramma

Ecco come chroot() modifica ciò che un processo può raggiungere:

graph TD;
    A[PHP Process] --> B{chroot('/var/www/jail')};
    B --> C[New root = /var/www/jail];
    C --> D[Working dir set to /];
    D -->|Path /data/config.txt| E[Allowed: inside jail];
    D -->|Path ../../etc/passwd| F[Blocked: nothing above /];

Nota: il confine è imposto dal sistema operativo, quindi si applica a ogni operazione sui file effettuata dal processo, non solo alle chiamate di funzione PHP.

Esercitazione

Pratica
Qual è lo scopo della funzione chroot in PHP?
Qual è lo scopo della funzione chroot in PHP?
Was this page helpful?