Mesmo por ser uma linguagem largamente usada, a exploração das vulnerabilidades do PHP cobram a atenção dos programadores, que devem verificar questões básicas de desenvolvimento para garantir o máximo de segurança em suas aplicações PHP. Grande parte dos erros são cometidos com a falta de cuidados na criação e validação dos formulários, neles se encontram as maiores brechas para ataques de hackers, que pretendem roubar dados de clientes ou derrubar o sistema.
Serão abordados alguns pontos cruciais que um bom programador PHP deve estar atento na construção do sistema web.
Ataques
SQL Injection e XSS attack
Qualquer aplicação pode receber dados externos do servidor, e só o programador vai dizer o que deve ser aceito ou ignorado pela aplicação. Ataques podem ser feitos via GET, POST, COOKIE e outros, alguns desses ataques são chamados de SQL Injections ou XSS que geralmente são feitos através de formulários que podem até possuir uma forma de validação no cliente, mas que certamente não é o suficiente, a validação desses dados é imprescindível para garantir segurança e estabilidade no sistema já que as SQL Injections são capazes de destruir o sistema, permitir o roubo e ainda a perda de todos os dados.
//Convertendo caracteres especiais para a realidade HTML
$varLimpa = htmlspecialchars($_POST['infoForm'], ENT_QUOTES, 'UTF-8');
//voltando os caracteres originais
$varSuja = htmlspecialchars_decode($varLimpa );
//filtros
$email = "clifton@example"; //Note the .com missing
if(filter_var($email, FILTER_VALIDATE_EMAIL)){
//válido
}
//recebendo um parâmetro GET, e validando se é inteiro
$id = filter_input('INPUT_GET', 'id', 'FILTER_VALIDATE_INT');
Configurações do php.ini
Algumas configurações básicas no arquivo php.ini podem prevenir o sistema de ser muito exposto, como por exemplo configurando a diretiva 'expose_php = off' (que reduz a quantidade de informações visíveis), variáveis como 'allow_url_fopen = Off' (impedem Remote File Inclusion e Local File Inclusion), 'display_errors = Off' (mensagens de erros não são exibidas), 'magic_quotes_gpc = Off' (converte caracteres especiais em barra invertida e impede o SQL Injection), 'register_globals = Off', variáveis globais desativadas.
Variáveis Globais
A partir da versão 4.2.0 do PHP, o padrão da diretiva register_globals passou de On para Off, o que significa que não é permitido o uso de variáveis globais. Como o PHP não necessita de declaração de variáveis para usá-las, esta diretiva poderia criar variáveis sem saber de onde elas vem, gerando códigos inseguros. Um exemplo podemos ver no código a seguir:
<?php
// define $autorizado = true somente se o usuário for autenticado
if (usuario_autenticado()) {
$autorizado = true;
}
// Porque nós não inicializamos $autorizado como false, ela pode ser
// definida através de register_globals, como usando GET autenticar.php?autorizado=1
// Dessa maneira, qualquer um pode ser visto como autenticado!
if ($autorizado) {
include "/dados/altamente/sensivel.php";
}
?>
No exemplo acima, a variável $autorizado não é inicializada, e com a diretiva register_globals ativa ela é facilmente alterada através do GET autenticar.php?autorizado=1, sendo assim, qualquer usuário pode acessar o conteúdo sensível mesmo que não passe pela função usuario_autenticado(). O ideal seria inicializar a variável $autorizado = false, assim nem com register_globals seria possível alterar seu valor.
O problema aqui não é a diretiva, mas sim o fato de não sabermos de onde vem os valores, garantir a correta validação dos dados enviados pelo usuário e que todas as variáveis sejam inicializadas corretamente. Desativar a diretiva resolve um problema, de onde vem os valores, os outros resolvemos com boas validações, limitando tamanho, quantidade, tipo e formato do dado enviado e a inicializando as variáveis com valores padrões, de preferência com o valor que define-se seguro.
Cookies
O atributo session.cookie_httponly configurado garante que os cookies de sessão que são armazenados no PHP só possam ser acessados por HTTP, tornando o sistema protegido de ataques como XSS, que utiliza JavaScript.
//php.ini
session.cookie_httponly=1
Tempo de Sessão
Com o parâmetro de tempo configurado em session_cache_expire, a sessão irá durar a quantidade de minutos informada. Quanto menor o tempo, menor vai ser o estrago que um invasor possa efetuar.
session_cache_expire(10); //tempo de sessão igual 10 minutos
session_start();
Upload de arquivos
Através do upload de arquivos é possível enviar scripts inteiros que podem dar controle completo do site e do servidor ao atacante, por isso o desenvolvimento de um sistema de upload de arquivos deve ser extremamente cauteloso. Muitas validações devem ser feitas no servidor para tentar impedir a entrada de scripts maliciosos, e a extensão do arquivo é a primeira coisa a ser validada, mas nunca a única, pois ela é facilmente alterada, assim como o mime-type e o content-type.
De fato não existe uma forma 100% segura de fazer uploads de arquivos, todas as precauções devem ser tomadas para garantir o máximo de segurança. Inicialmente define quais tipos de arquivos serão aceitos, valide os formatos e tenha certeza de que está salvando no servidor os arquivos com as extensões que são permitidas, se for imagem verificamos se possui dimensões e para remover possíveis scripts injetados podemos redimensionar a imagem, em outros formatos pode se abrir o arquivo e procurar por <?php ?>, valide o usuário também, permitir que somente usuários cadastrados possam fazer uploads, mas isso não adiantará se não tiver um bom sistema de login com senhas fortes e a prova de SQL Injection, e por último, salve os arquivos em uma pasta onde não são executados scripts e que as permissões de acesso sejam restritas ao php somente.
list($largura, $altura) = getimagesize($_FILES["foto"]["tmp_name"]);
if($largura=="" || $altura ==""){
//ARQUIVO INVÁLIDO
}
//validando via magic byte
$filehandle = fopen($_FILES['file']['tmp_name'],"r");
// get file's magic number
$MNumber = bin2hex(fread($filehandle,4));
if ($MNumber!= "d4c3b2a1") {
echo 'bad file format';
exit;
}
No exemplo acima é usado como validação o chamado 'magic byte', uma assinatura encontrada no início dos arquivos quando lidos como texto, com ela é possível validar alguns formatos onde existe uma assinatura comum, porém essa assinatura também pode ser forjada, então não dispensa outras validações e nem outras medidas de segurança comentadas anteriormente.
Restrição de logs
Quanto menos informações, em caso de erros e exceções, forem mostradas, mais a aplicação estará protegida.
Estas informações podem ser controladas através dos parâmetros do error_reporting.
Também as configurações das funções 'log_errors=On' e 'display_errors'.
int error_reporting ([ int $nível ] )//sintaxe
Níveis disponíveis para configuração do 'error_reporting':
1 E_ERROR
2 E_WARNING
4 E_PARSE
8 E_NOTICE
16 E_CORE_ERROR
32 E_CORE_WARNING
64 E_COMPILE_ERROR
128 E_COMPILE_WARNING
256 E_USER_ERROR
512 E_USER_WARNING
1024 E_USER_NOTICE
6143 E_ALL
2048 E_STRICT
4096 E_RECOVERABLE_ERROR
Desabilitando funções e classes
Através de configurações no php.ini, é possível desabilitar algumas funções e classes, utilizando as diretivas:
- disable_functions: diretiva que desabilita funções internas por motivos de segurança
- disable_classes: diretiva que desabilita classes por questões de segurança
Conclusão
Hoje em dia as aplicações web são constante e fortemente atacadas, necessitando ao máximo de segurança em seus códigos.
Referências