W3docs

chroot()

Aprenda como a função chroot() do PHP altera o diretório raiz de um processo para criar um ambiente de sistema de arquivos isolado, com sintaxe e exemplos.

Função PHP chroot()

A função chroot() altera o diretório raiz do processo em execução atual para o diretório especificado e, em seguida, define o diretório de trabalho atual como /. Após a chamada, o processo não consegue mais ver ou acessar nenhum arquivo acima dessa nova raiz — ele fica "preso" dentro da árvore de diretórios. Essa técnica é comumente chamada de chroot jail.

Esta página explica o que chroot() faz, quando você usaria (e não usaria) essa função, sua sintaxe e as limitações que você precisa conhecer antes de depender dela.

Sintaxe

chroot(string $directory): bool
ParâmetroDescrição
$directoryO caminho para o diretório que se torna a nova raiz (/) do processo.

Valor de retorno: true em caso de sucesso, false em caso de falha.

Requisitos

chroot() não está disponível em todos os ambientes. Antes de usá-la, tenha em mente estas restrições:

  • Funciona apenas em SAPIs CLI e CGInão está disponível na maioria dos SAPIs de módulo, como mod_php ou PHP-FPM executando uma requisição web típica.
  • Não é implementada no Windows.
  • O processo chamador precisa ter privilégios de root (superusuário). Um usuário normal não pode alterar o diretório raiz.

Por causa dessas limitações, chroot() é usada principalmente em daemons PHP CLI de longa duração e scripts de worker, não em código que lida com requisições HTTP comuns.

Exemplo Básico

Este script prende o processo dentro de /var/www/jail e, em seguida, lê um caminho relativo à nova raiz:

<?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";
}

Após a chamada chroot(), o caminho /data/config.txt na verdade se refere a /var/www/jail/data/config.txt no sistema de arquivos real. O processo simplesmente não consegue expressar um caminho que escape da prisão.

Confirmando o Diretório de Trabalho

Como chroot() também move o diretório de trabalho para /, você pode confirmar a mudança com getcwd():

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

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

Se você precisar de um diretório de trabalho diferente dentro da prisão, defina-o explicitamente com chdir() após a chamada chroot().

Por que Usar chroot()

O objetivo de chroot() é o isolamento. Uma vez que um processo está preso:

  • Ele não pode abrir, ler ou gravar arquivos fora da nova raiz, mesmo com caminhos absolutos.
  • Um bug ou exploit que tente atravessar diretórios (../../etc/passwd) não tem para onde ir — não existe caminho acima de /.
  • Você pode fornecer uma árvore de diretórios mínima (apenas os arquivos de que o worker realmente precisa), reduzindo a superfície de ataque.

Um padrão comum é iniciar um daemon como root, chamar chroot() para confiná-lo em uma sandbox e, em seguida, abandonar os privilégios com posix_setuid() / posix_setgid() para que o processo preso não mais seja executado como root.

chroot() vs open_basedir

Esses dois recursos são frequentemente confundidos. Eles resolvem um problema semelhante em níveis muito diferentes:

chroot()open_basedir
NívelRaiz do processo no sistema operacionalVerificação de caminho no mecanismo PHP
Onde definidoNo código em tempo de execuçãophp.ini, .htaccess, pool FPM
Funciona em SAPIs webNão (apenas CLI/CGI)Sim
Precisa de privilégios de rootSimNão
SegurançaPrisão imposta pelo SOConsultiva, pode ser enfraquecida por links simbólicos

Se você apenas precisa manter uma requisição web normal dentro de um diretório, open_basedir é a ferramenta prática. Use chroot() quando você controla um processo CLI e deseja uma fronteira real no nível do SO.

Limitações e Armadilhas

  • Não é uma fronteira de segurança perfeita. Um processo ainda em execução como root dentro de um chroot muitas vezes pode escapar. Sempre abandone os privilégios após a prisão.
  • Dependências ausentes. A prisão não tem /lib, /etc, /usr a menos que você os coloque lá. Funções que dependem de arquivos do sistema (consultas DNS, dados de localização, fusos horários, bibliotecas dinâmicas) podem falhar dentro da prisão.
  • Irreversível para o processo. Não existe unchroot(); a mudança dura por toda a vida do processo.
  • Dependente do ambiente. Como a disponibilidade depende do SAPI e do SO, proteja as chamadas e verifique o valor de retorno em vez de assumir o sucesso.

Conclusão

chroot() confina um processo PHP a uma única árvore de diretórios, alterando sua raiz para esse diretório e redefinindo o diretório de trabalho para /. É uma poderosa ferramenta de isolamento no nível do SO para daemons CLI privilegiados, mas requer root, está limitada a CLI/CGI e não está disponível no Windows. Para restrições por requisição em uma pilha web normal, use open_basedir e trate chroot() como uma camada de uma estratégia de defesa em profundidade. Para saber mais sobre como trabalhar com caminhos e o sistema de arquivos, veja chdir(), getcwd() e o capítulo PHP Filesystem.

Diagrama

Veja como chroot() remodela o que um processo pode acessar:

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: A fronteira é imposta pelo sistema operacional, por isso se aplica a todas as operações de arquivo que o processo realiza, não apenas às chamadas de funções PHP.

Prática

Prática
Qual é o propósito da função chroot no PHP?
Qual é o propósito da função chroot no PHP?
Was this page helpful?