Esta apresentação mostra algumas recomendações para se programar em PHP utilizando alguns recursos de segurança.
As recomendações feitas foram baseadas em partes de documentos OWASP específicos sobre a linguagem - acesso em 09/09/2016 - e adaptadas pelo autor para esta apresentação:
A OWASP é uma fundação sem fins lucrativos, fundada em 21 de abril de 2004 (data em que foi criada como fundação).
Apesar das pressões comerciais, ela não é mantida por nenhuma empresa específica de tecnologia, tornando assim seu conteúdo imparcial e transparente.
Além disso, vale destacar que os materiais são colaborativos e abertos e podem ser acessados diretamente através do site da Fundação - https://www.owasp.org .
Quando falamos da linguagem no PHP devemos considerar 3 pontos importantes que devem ser levados em consideração e por isso estar devidamente atualizados e tratados de vulnerabilidades de segurança:
Apesar de não fazerem parte da linguagem, mas por estarem intimamente relacionados, poderíamos adicionar também outros pontos focais que devem ser seguros:
Esquecer de um desses pontos pode comprometer a segurança da sua aplicação portanto é importante levar em consideração isso ao escolher fornecedores da sua aplicação, como servidores de hospedagem, por exemplo.
Falar detalhadamente sobre esses pontos vai além do escopo dessa apresentação, mas é sempre importante ressaltar que a tarefa de manter a segurança de uma aplicação envolve um conjunto de recursos, ou seja, se o programador fizer a sua parte, programando de maneira segura, ele estará cuidando apenas de uma parte importante dessa estrutura de segurança.
Baseada em uma importante pesquisa sobre vulnerabilidades comuns em aplicações PHP, o OWASP criou o artigo com recomendações conhecido como PHP Top 5
A metodologia utilizada na preparação deste artigo é rever todos os lançamentos Bugtraq contendo a palavra "PHP" e categorizar cada falha único.
PHP é também uma linguagem de templates ( Você pode combinar o código PHP com HTML para saidas dinâmicas, etc ).
Porém, por padrão, PHP não escapa o HTML do conteúdo da String dando abertura para um ataque XSS (https://pt.wikipedia.org/wiki/Cross-site_scripting).
Um desses exemplos é o vídeo: https://www.youtube.com/watch?v=LGWQE4LTeuk em que o autor cria uma classe com uma WhiteList de tags aceitáveis de saída.
SQL injection é um dos ataques mais conhecidos da comunidade. Você pode evitá-lo usando recursos como:
Usando MySQLi ou PDO - usar instruções parametrizadas (parameterized statements ou prepareted statements );
As modificações feitas em PHP.ini devido a recursos ou bibliotecas utilizadas devem ser feitas de maneira controlada e documentada.
É importante ao desenvolvedor conhecer bem o arquivo de configuração PHP.ini e seus parâmetros, pois este influencia na execução de sua aplicação.
Certifique-se de que os usuários só podem afetar as operações de arquivo para o grau que você tinha em mente;
Existem algumas características da linguagem que se forem ignoradas podem em algum momento comprometer a segurança da aplicação.
Forçar o tipo de variáveis de parâmetro e de retorno em funções e métodos de objeto (recursos novos do PHP 7.0 e 7.1 e parcialmente implementados nas versões anteriores);
Muitas bibliotecas da linguagem usam meios diferentes de reportar um determinado erro (algumas retornam um array com informações de código de erro, outras disparam exceções, etc, etc) permitindo que um código defeituoso continue rodando;
Em muitas outras línguas, e a maioria das linguagens de alto nível que competem com PHP, condições de erro que são causados ​​por erros de desenvolvedor, ou erros de execução que o desenvolvedor não conseguiu prever, fará com que o programa pare de correr, que é a coisa mais segura a fazer .
É importante, no contexto desse código que o programador saiba tudo o que acontece e onde não foi possível concluir determinada operação ( ex: Erro de login do banco, banco não encontrado, query inválida, etc etc );
Isso não deve ser mostrado ao usuário final, pois pode gerar informação para um possível atacante do sistema;
Gerar uma exceção, parando a execução do programa e gravando em log qual foi a exceção ocorrida em detalhes para um debug por parte do desenvolvedor/ administrador do sistema;
Esta característica muitas vezes esconde erros por parte do desenvolvedor ou injeções de dados inesperados:
Ele também sugere que sempre que possível utilize o máximo de informações possíveis que possam ser obtidas, utilizando a função error_reporting function;
Não suprimir erros e seguir sempre os detalhes das informações de alerta, para escrever um código de melhor qualidade;
Caso você tenha receio de parar sistemas de produção com essa prática, mesmo que mantendo a mesma versão do PHP atualizada com Patchs de segurança você pode:
Criar um ambiente de integração contínua que teste o código rodando em diversos ambientes de configuração;
Antes de realizar qualquer atualização realizar um backup de imagem, guardando arquivos e configurações do ambiente e seus respectivos componentes instalados/configurados;
Vale ressaltar, como anteriormente, que a configuração do PHP.ini deve ser detalhadamente revisada, para evitar falhas de segurança por configurações.
Não existe um padrão na linguagem para roteamento de urls fazendo com que várias soluções diferentes sejam implementadas nesse aspecto.
O problema disso é que programadores desavisados podem criar seus próprios meios abrindo brechas de segurança.
Vulnerabilidade de execução remota - durante o upload de arquivos, se sobe um arquivo que pode ser executado pelo servidor remotamente ao invés de ser simplesmente disponibilizado.
Visualização de códigos sensíveis - Código fonte, incluindo arquivos de configuração, são armazenadas em diretórios acessíveis ao público junto com os arquivos que se destinam a ser baixado (como ativos estáticos).
Nesse caso é recomendado como única solução pelo OWASP o uso de arquivos .htaccess para limitar esses acessos;
Ao utilizar os arrays do PHP, mantenha uma uniformidade ao buscar as informações e cuidado para não confundir seus valores:
Logo não faz sentido esperar uma informação determinada em $array[0] já que você está usando um nome como chave de valor;
Para ter certeza desse comportamento, ou seja, quando usar como chave o índice padrão, ou usar um nome como chave, você pode usar as funções array_values ( retornaria array([0] = “Jamayca”, [1] = “Pierez”) ou array_keys ( retornaria array([0]=>”Betho”, [1] = “Karla”)) em seu foreach.
Esse pequeno detalhe de comportamento gerou um problema de segurança grave já corrigido no Drupal 7 segundo esse link: https://www.drupal.org/SA-CORE-2014-005
Existem algumas funções como addslashes, mysql_escape_string e mysql_real_escape_string podem não realizar completamente suas funções ou não estão sendo mais suportadas em versões da linguagem futuras ( deprecated ).
Este super global não é recomendado, uma vez que inclui não apenas dados de GET e POST, mas também os cookies enviados pelo pedido.
Todos estes dados são combinados em uma matriz, o que torna quase impossível determinar a fonte dos dados.
Isso pode levar a confusão e torna seu código propenso a erros, que podem levar a problemas de segurança.
Quando utilizamos o $_REQUEST o PHP prioriza a precedência das variáveis globais de acordo com a configuração variables_order.
Se retirarmos algumas dessas letras, a super global $_REQUEST não conseguirá pegar alguma dessas possibilidades:
Nem todos os dados em $_SERVER pode ser falsificado pelo usuário, mas uma quantidade considerável no que puder, em particular e, especialmente, tudo o que lida com cabeçalhos HTTP (que começar com HTTP_);
As bibliotecas e os projetos escritos em PHP são muitas vezes inseguros devido aos problemas destacados acima, especialmente quando frameworks web adequadas não forem usados.
Não confie em código PHP que você encontrar na web, como muitas vulnerabilidades de segurança pode se esconder em código aparentemente inocente.
Uma solução comum é desligar todos os avisos, que é exatamente o oposto do que deveria ser feito (ver acima), e leva a progressivamente piora do código.
A verificação do tipo de arquivo enviado deve ser feita através de extensões/librarys específicas para isso pois códigos como $_FILES['some_name']['type'] podem ser manipulados, por ser uma informações enviadas via cliente;
Uma sugestão de extensão para ser usada e presente no OWASP é http://php.net/manual/pt_BR/class.finfo.php;
Uma solução que pode ajudar parcialmente neste processo é utilizar serviços de Storage de informações, ao invés de guardar os arquivos enviados no mesmo servidor que sua aplicação, fazendo com que a execução do arquivo, dessa forma, seja dificultada;