Capítulo 42. Modo Seguro (Safe Mode)

Índice
Segurança e o modo seguro
Funções restringidas/desabilitadas pelo modo seguro

O modo seguro do PHP é uma tentativa de resolver o problema de servidores compartilhados. É arquiteturalmente incorreto tentar resolver esse problema no nível do PHP, mas já que as alternativas no nível dos servidores e dos sistemas operacionais não são muito eficientes, muitas pessoas, especialmente provedores de internet, usam o modo seguro por enquanto.

Segurança e o modo seguro

Tabela 42-1. Diretivas de configuração de segurança e do modo seguro

NomeValor PadrãoAlterável
safe_mode"0"PHP_INI_SYSTEM
safe_mode_gid"0"PHP_INI_SYSTEM
safe_mode_include_dirNULLPHP_INI_SYSTEM
safe_mode_exec_dir""PHP_INI_SYSTEM
safe_mode_allowed_env_varsPHP_PHP_INI_SYSTEM
safe_mode_protected_env_varsLD_LIBRARY_PATHPHP_INI_SYSTEM
open_basedirNULLPHP_INI_SYSTEM
disable_functions""PHP_INI_SYSTEM
disable_classes""PHP_INI_SYSTEM
Para mais detalhes e definições das constantes do PHP_INI_* veja ini_set().

Breve descrição das diretivas de configuração.

safe_mode boolean

Habilitar ou não o modo seguro do PHP leia o capítulo de Segurança para mais informação..

safe_mode_gid boolean

Por padrão, o modo seguro faz checagem comparando o UID quando abre arquivos. Se você quiser diminuir a especificidade do teste para compara com o GID, então ligue a diretiva safe_mode_gid. Escolher entre usar checagem de UID (FALSE) ou de GID quando acessar um arquivo.

safe_mode_include_dir string

Checagem de UID/GID não são feitas quando é feita inclusão de arquivos desse diretório e seus subdiretórios (diretório também deve estar no include_path ou o caminho completo deve ser incluso).

A partir do PHP 4.2.0, essa diretiva pode receber vários diretórios separados por dois pontos (ponto-e-vírgula no Windows) similar à diretiva include_path, ao contrário de apenas um diretório

A restrição especificada é, na verdade, um prefixo, não um nome de diretório. Isso significa que "safe_mode_include_dir = /dir/incl" também permite acesso a "/dir/include" e "/dir/incls" se eles existirem. Quando você quiser restringir o acesso apenas ao diretório especificado, termine com uma barra. Por exemplo: "safe_mode_include_dir = /dir/incl/"

safe_mode_exec_dir string

Se o PHP for usado no modo seguro, system() e as outras funções que executam programas do sistema se recusam a executar programas que não estão no diretório atual. Você deve usar / como separador diretório em todos os ambientes, inclusive o Windows.

safe_mode_allowed_env_vars string

Editar certas variáveis de ambientes pode ser uma falha de segurança em potencial. Essa diretiva contem uma lista de prefixos delimitados por vírgulas. No modo seguro, o usuário só pode alterar as variáveis de ambiente cujo nome começa com um dos prefixos dessa lista. Por padrão, os usuários só poderão ser capazser de editar variáveis de ambiente que começão com PHP_ (ex.: PHP_FOO=BAR).

Nota: Se essa diretiva estiver vazia, o PHP deixará o usuário modificar QUALQUER variável de ambiente!

safe_mode_protected_env_vars string

Essa diretiva contem uma lista delimitada por vírgulas de varáveis de ambiente que o usuário final não será capaz de mudar usando putenv(). Essas variáveis serão protegidas mesmo que safe_mode_allowed_env_vars esteja configurada para permitir que elas sejam mudadas.

open_basedir string

Limita os arquivos que podem ser abertos ao diretório especificado e seus subdiretórios, incluindo o arquivo em si. Essa diretiva NÃO é afetada pelo estado do modo seguro, seja este ligado ou desligado.

Quando um script tenta abrir um arquivo com, por exemplo, fopen() ou gzopen(), a localização do arquivo é checada. Quando o arquivo está fora do diretório especificado, o PHP se recusará a abrí-lo. Todos os links simbólicos também passam pelo teste, não sendo possível evitar essa restrição com um symlink.

O valor especial . indica que o diretório de trabalho, onde o script é rodado, será usado como o diretório base. Isso é, no entanto, um pouco perigoso, já que o diretório de trabalho do script pode ser facilmente alterado com a função chdir().

In httpd.conf, open_basedir can be turned off (e.g. for some virtual hosts) the same way as any other configuration directive with "php_admin_value open_basedir none".

No Windows, separe os diretórios com ponto-e-vírgula. Em todos os outros sistemas, separe os diretórios com dois pontos. Como módulo do Apache, caminhos do open_basedir dos diretórios pais são herdados automaticamente agora.

A restrição especificada com open_basedir é na verdade um prefixo, não um nome de diretório. Isso significa que "open_basedir = /dir/incl" também permite acesso à "/dir/include" e "/dir/incls" se eles existirem. Quando você quiser restringir o acesso para apenas o diretório especificado, termine com uma barrra. Por exemplo: "open_basedir = /dir/incl/"

Nota: Suporte para diretórios múltiplos foi adicionado na versão 3.0.7.

O padrão é permitir que todos os arquivos sejam abertos.

disable_functions string

A diretiva permite que você desabilite certas funções por razões de segurança. Ela recebe uma lista de nomes de funções separadas por vírgula. disable_functions não é afetada pela diretiva Safe Mode.

Essa diretiva deve ser configurada no php.ini Você não pode, por exemplo, configurá-la no httpd.conf.

disable_classes string

Essa diretiva permite que você desabilite certas classes por razões de segurança. Ela recebe uma lista de nomes de funções separadas por vírgula. disable_functions não é afetada pela diretiva Safe Mode.

Essa diretiva deve ser configurada no php.ini Você não pode, por exemplo, configurá-la no httpd.conf.

Availability note: Essa diretiva está disponível na versão 4.3.2 ou superior.

Veja também: register_globals, display_errors, e log_errors

Quando o safe_mode está ligado, o PHP checa se o proprietário do script atual bate com o proprietário do arquivo a ser operado por uma função de arquivo. Por exemplo:
-rw-rw-r--    1 rasmus   rasmus       33 Jul  1 19:20 script.php 
-rw-r--r--    1 root     root       1116 May 26 18:01 /etc/passwd
Executando esse script.php
<?php
readfile
('/etc/passwd');
?>
resulta nesse erro quando o modo seguro estiver habilitado:
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 
allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2

No entando, em certos ambientes uma checagem rígida de UID não é apropriada e uma checagem mais leve de GID é suficiente. Isso é suportado através da diretiva safe_mode_gid. Atribuindo a ela o valor On faz a checagem de GID, mais leve e atribuindo a ela o valor Off (o padrão) faz a checagem UID.

Se, ao invés de safe_mode, você editou um diretório em open_basedir, então todas as operações de arquivos serão limitadas a arquivos no diretório especificado e seus subdiretórios. Por exemplo (httpd.conf do Apache de exemplo):
<Directory /docroot>
  php_admin_value open_basedir /docroot 
</Directory>
Se você rodar o mesmo script.php com essa configuração de open_basedir então esse será o resultado:
Warning: open_basedir restriction in effect. File is in wrong directory in 
/docroot/script.php on line 2

You can also disable individual functions. Note that the disable_functions directive can not be used outside of the php.ini file which means that you cannot disable functions on a per-virtualhost or per-directory basis in your httpd.conf file. If we add this to our php.ini file:
disable_functions readfile,system
Then we get this output:
Warning: readfile() has been disabled for security reasons in 
/docroot/script.php on line 2