Features nem sempre são vantagens, ainda mais quando usadas de forma incorreta. Apesar do PHP possuir uma documentação das mais completas e dinâmicas, às vezes as explicações podem gerar confusão ou diferentes interpretações por ser bastante breve e livre de observações. Veja alguns dos problemas que essas features podem causar:
Apesar de que a diretiva register_globals ter se tornado deprecated no PHP 5 e pretendem remover no PHP 6, é sempre bom falar sobre isso que chegou a causar muita dor de cabeça a algum tempo.
Quando essa diretiva encontra-se ligada, o PHP injeta variáveis extras no script como variáveis de requisição do HTML. O problema disso é que o desenvolvedor pode ser inocente ao ponto de não se preocupar que podem haver mudanças no valor dessas variáveis por usuários mal intencionados ou mesmo criar variáveis potencialmente perigosas.
Exibir os erros por mais que se tratem apenas de advertências é essencial. É fato de que você nem sempre enxergará todos se não forem mostrados visualmente. Em contrapartida, uma vez que o website está no ar, a exibição de erros deve ser desligada, pois o PHP providencia informações detalhadas que poderão chegar as mãos de um usuário mal intencionado.
Exibindo os erros num ambiente de desenvolvimento:
Escondendo os erros quando o website estiver no ar, porém gravando as mensagens num arquivo de log:
ini_set("error_log", "/path/to/error/log");
De maneira alternativa, é possível usar error_reporting(E_ALL | E_STRICT) que funcionaria como um backward compat.
Talvez a vulnerabilidade mais comum na maioria dos websites. O problema está no desenvolvedor não filtrar os dados de campos de formulários HTML e verificar as possíveis saídas.
Por exemplo, temos o seguinte formulário:
<form action="comment.php" method="POST" accept-charset="UTF-8" enctype="multipart/form-data" name="commentForm">
<textarea name="message" id="message">textarea>
<input type="submit" name="submit" value="Enviar" id="submit" />
O código exibe o seguinte dado:
A vulnerabilidade é devido ao fato de que não há filtragem da entrada e nem o escape da saída de dados. Se alguém escrever no textarea o seguinte código javascript:
Se a aplicação não cuidar de escapar a saída de dados, cada requisição de página será seguida de um popup de alerta do Javascript. Para evitar isso, o programador deve filtrar quaisquer tipo de tags HTML dos dados (ou mesmo permitir apenas algumas, como fazem sistemas de blogs como o Wordpress):
$clean_message = strip_tags($_POST['message']);
Além disso, deve-se proibir/limitar o uso de tags HTML, podemos fazer isso com htmlentities, porém não é a única forma de se fazer isso:
htmlentities($clean_message, ENT_QUOTES, "UTF-8";
Recomendo usar o HTML Purifier para filtrar qualquer tipo de dados potencialmente inseguros e testar cada formulário com o XSS cheat sheet.
Exposição de informações de segurança
Guardar informações tais como senhas de banco de dados e dados do tipo devem ser feitas de forma bem cautelosa, pois se estas puderem ser vistas por um usuário, as chances de perder o banco de dados são grandes.
Muitos programadores usam a extensão .inc para mostrar que o arquivo é incluído pelas funções require ou include (e suas variações _once). Não há problemas em usá-las, desde que a extensão tenha regras de processamento pelo servidor Web.
No arquivo de configuração do Apache, o tipo de arquivo padrão para extensões desconhecidas é de texto (text/plain). Se a extensão .inc não for lida pelo PHP, as informações estarão visíveis em formato texto e portanto, não sendo interpretadas como código.
É possível evitar isso guardando esses arquivos fora da pasta raiz (em servidores *nix a pasta raiz costuma ser /public_html). Melhor ainda seria sempre guardar apenas arquivos essenciais na pasta raiz. Caso você não tenha acesso a essas pastas, existem 2 soluções alternativas: