Tornando o PHP mais seguro
A própria natureza de correr sites dinâmicos num servidor constitui um projeto arriscado. Os métodos aqui discutidos diminuem o risco de invasão e reduzem os danos causados por uma brecha. Como sempre, devemos estar informados sobre novas vulnerabilidades que vão surgindo, aplicando os patches respectivos.
O PHP pode ser instalado num servidor como interpretador CGI ou módulo Apache. Cada um destes métodos tem vantagens e desvantagens.
No primeiro caso, é possível ter processos diferentes a correr para utilizadores diferentes em virtual hosts diferentes, usando o suEXEC do Apache. No entanto, este método de instalação pode ser lento e é fértil em riscos de segurança, quando mal configurado.
Em alternativa, pode instalar-se o PHP como módulo Apache, que é o método em que nos vamos focar neste artigo. Neste caso, pode-se ainda optar por compilar o PHP como módulo estático ou dinâmico. O estático tem como vantagem, uma melhor performance, mas quando se decidir fazer um upgrade, tem que se recompilar tanto o Apache como o PHP. Com o dinâmico, perde-se alguma performance, é necessário ter o Apache compilado com suporte para módulos dinâmicos, fazendo uso do módulo mod_so, mas os upgrades de PHP são bem mais simples. A escolha deve depender das necessidades particulares de cada um – especialmente a importância da performance versus conveniência de um fácil upgrade.
Módulo estático
É necessário compilar o PHP antes da compilação do Apache com os comandos:
./configure –with-mysql=/usr/local/mysql
–with-apache=/path/to/apache_source –enable-safe-mode
make
su
make install
Copia-se então o arquivo dir_apache/mod_security.c para a pasta src/modules/extra do Apache, compilando-se este de seguida, seguindo os passos tradicionais (que não são do âmbito deste artigo), adicionando as seguintes opções: –activate-module=src/modules/extra/mod_security –enable-module=security –activate-module=src/modules/php4/libphp4.a.
Módulo dinâmico
Instala-se primeiro o Apache e depois compila-se o PHP com os seguintes comandos:
./configure –with-mysql=/usr/local/mysql –with-apxs=/usr/sbin/apxs –enable-safe-mode
make
su
make install
Para instalar o mod_security como módulo dinâmico, extraem-se as sources e corre-se o comando apxs -cia mod_security.c para instalar.
Seja qual for o método de instalação escolhido, devem-se ativar as opções estritamente necessárias, porque incluir mais funcionalidades significa aumentar o risco de vulnerabilidades. Adicionalmente, em ambiente multi-utilizadores, é recomendável ativar o Safe Mode com -enable-safe-mode.
Configuração do Apache
Adicionam-se as seguintes linhas ao httpd.conf para ativar o PHP:
LoadModule php4_module libexec/libphp4.so
AddModule mod_php4.c
AddType application/x-httpd-php .php
AddType application/x-httpd-php .php3
AddType application/x-httpd-php .inc
AddType application/x-httpd-php .class
As diretivas AddType asseguram que todos os arquivos com extensões .php, .php3, .inc, e .class são processados como scripts PHP. Muitos programadores usam *.class e *.inc como nomes de
arquivos externos incluídos nos seus scripts. Sem estas diretivas, estes
arquivos seriam mostrados como texto puro no navegador, revelando potencialmente passwords ou outros dados sensíveis.
Outra forma de conseguir o mesmo efeito, é usar a diretiva Files para negar o acesso a determinados
arquivos. Por exemplo, as linhas
Deny from all
Satisfy All
negam o acesso a todos os arquivos cujo nome termine em .inc ou .inc.php, estando apenas acessíveis usando include() ou require() num script.
Se não se quiser que seja óbvio o fato de se estar a usar PHP num servidor, pode-se usar uma extensão diferente para os scripts. Usando AddType application/x-httpd-php .dhtml teríamos o Apache a interpretar todos os
arquivos com extensão .dhtml como scripts PHP. Ainda assim, esta é uma medida um pouco superficial, pois há outras formas de se descobrir que um servidor está a correr PHP.
Defesa contra injection com mod_security
O mod_security é um motor de detecção e prevenção de intrusão para aplicações Web que operam como módulo Apache. Todos os GET’s e POST’s são verificados e aqueles considerados maliciosos são simplesmente rejeitados de acordo com a configuração existente.
Para ativar este módulo, adicionam-se as seguintes linhas ao arquivo httpd.conf:
LoadModule security_module libexec/mod_security.so
AddModule mod_security.c
Para configurá-lo para monitorizar pedidos GET e POST, adicionam-se as linhas:
# Ligar ou desligar o filtro: On or Off
SecFilterEngine On
# Verificar codificação do URL
SecFilterCheckURLEncoding On
# Verificar codificação Unicode
SecFilterCheckUnicodeEncoding On
# Permitir apenas bytes de um intervalo
SecFilterForceByteRange 0 255
# Salvar no log apenas atividades suspeitas
SecAuditEngine RelevantOnly
# O nome do arquivo de log
SecAuditLog logs/audit_log
# Colocar o nível de debug no mínimo
SecFilterDebugLog logs/modsec_debug_log
SecFilterDebugLevel 0
# Ativar a monitorização de POST
SecFilterScanPOST On
# Por padrão, apresentar ERRO 500
SecFilterDefaultAction “deny,log,status:500”
Esta é a configuração mais básica mas já proporciona sérias vantagens:
– Remove //;
– Remove ./;
– Faz o decoding dos URL’s;
– Substitui bytes nulos () por espaços;
– Valida a codificação dos URL’s;
– Valida a codificação unicode;
– Verifica o intervalo de bytes.
Além destas medidas, queremos usar o mod_security para prevenir ataques por SQL injection e cross-site scripting (XSS). Para o conseguirmos, basta adicionarmos as seguintes linhas:
SecFilter “\.\./”
SecFilter “<(.|\n)+>”
SecFilter “‘”
SecFilter “””
A primeira linha previne o acesso a arquivos fora do diretório do site. A segunda detecta < e >, fazendo com que o servidor rejeite pedidos com tags HTML e ajudando na proteção contra os ataques XSS. As últimas duas linhas filtram as plicas e as aspas respectivamente, dificultando os ataques por SQL injection.
Usando o Safe mode
Uma das maiores preocupações ao nível da segurança do PHP num ambiente multi-utilizador é o fato dos scripts correrem sob o ID do utilizador do servidor. Isto não só significa que os utilizadores PHP têm acesso a qualquer recurso a que o servidor tenha acesso, como todos os scripts PHP têm acesso entre si, uma vez que todos operam com o mesmo ID de utilizador.
Em termos de arquitetura, este problema é melhor resolvido ao nível do sistema operativo mas, embora existem várias soluções, não há nenhuma completamente satisfatória. Assim, os responsáveis pelo desenvolvimento do PHP inventaram o Safe Mode.
O Safe Mode assegura que qualquer arquivo que é acedido por um script, é propriedade do proprietário do dito script. Para ativar o Safe Mode, deve compilar-se o PHP como acima descrito e depois ativar no php.ini, colocando a variável safe_mode a on. Quando está ligado, uma versão ligeiramente mais relaxada pode ser ativada usando safe_mode_gid=on, que utiliza o grupo como elemento de comparação nos
arquivos que estão a ser acedidos.
Existem algumas opções a considerar quando se configura o Safe Mode. As mais importates são:
safe_mode_exec_dir = /some/dir
— As chamadas a funções que executam arquivos binários como o system() só conseguirão correr aqueles que estiverem no diretório especificado;
safe_mode_allowed_env_vars = PHP_
— Os utilizadores só poderão iniciar environment variables com o prefixo PHP_. Este prefixo pode ser qualquer outra coisa, ate mesmo vários valores separados por vírgulas. No entanto, não se deve deixar em branco, uma vez que tal permitiria aos utilizadores iniciar qualquer environment variable.
Outras configurações PHP
Para além do Safe Mode existem outras opções no php.ini cuja configuração pode fazer a diferença ao nível da segurança:
open_basedir = /some/dir
— limita os arquivos que o PHP pode abrir e ler ao diretório especificado. Usando . como diretório, limita-se o PHP ao diretório em que o script está. Pode especificar-se diretórios múltiplos separados por ; (ponto e vírgula). O valor por defeito desta opção permite ao PHP aceder a qualquer diretório.
disable_functions = function1,function2
— permite ao administrador proibir o uso de funções específicas, que devem ser listadas por nome e separadas por vírgula.
expose_php = Off
— Normalmente o PHP mostra que está instalado no servidor, adicionando headers extra. Desativando esta opção, isso deixa de acontecer.
display_errors = Off
— Colocando esta opção em Off evita que o PHP mostre eventuais erros de execução, que poderiam revelar informações importantes de configuração do servidor, como paths e estrutura do acesso a base de dados.
log_errors = On
— Para logar os erros escondidos na opção anterior para um arquivo
error_log = /var/log/php_errors
— Para definir o arquivo a ser usado na opção anterior.
register_globals = Off
— evita que variáveis ENVIRONMENT, GET, POST, Cookie, e Built-in sejam registadas como globais. Se estes valores forem globais, a programação é bastante mais fácil mas aumenta o risco de segurança, caso o código não esteja bem cuidado.