Aplicações mais seguras com PHP - parte II

Aplicações mais seguras com PHP - parte II

Dando continuidade ao artigo sobre aplicações mais seguras com PHP, trouxe mais alguns itens que visam deixar a aplicação menos vulnerável. Conforme o artigo anterior, alguns itens não estão diretamente relacionados com PHP, mas sim com um escopo mais abrangente. Mas são essenciais para deixar a aplicação menos vulnerável.

Se ainda não viu a primeira parte, sugiro que comece por lá: só clicar aqui!


Desative a listagem de diretórios

Um problema até bem simples e fácil de ser mitigado é a exposição de dados. Um dos itens que contribuem para isso é um recurso comum na maioria dos servidores web: listagem de diretórios. Que nada mais é do que a listagem de arquivos e pastas presentes dentro de um determinado diretório.

Para evitar que pastas e arquivos fiquem expostos, é altamente recomendável que a listagem de diretórios seja desativada. Uma "solução" simples é criar um arquivo index.html dentro de todos os diretórios, mas como é algo que pode ser esquecido e, dependendo da aplicação, muito custoso.

A maioria dos servidores web dispõem desse recurso e o deixam de forma totalmente opcional. A solução mais segura aqui é desativar diretamente no arquivo de configuração do servidor.

Nginx

autoindex off;

Apache

Options FollowSymLinks

Lembrando que existe a opção de desativar apenas para um virtual host, pasta ou para todo o servidor.

Limite as requisições de um mesmo cliente

Limitar a quantidade de requisições que um mesmo cliente pode executar em um determinado intervalo não elimina a possibilidade de exploração de alguma vulnerabilidade, mas ajuda a atrasar o processo.

Aqui não existe um valor determinado, pois depende do cenário e da necessidade da sua aplicação. Muitas requisições sequenciais em um baixo intervalo por um mesmo cliente, pode indicar a possível verificação ou exploração de vulnerabilidade. Nesse caso, vale fazer o bloqueio temporário do cliente e notificar o time de segurança sobre a atividade fora do normal.


WAF não é um firewall de rede

É importante entender o domínio de cada um e onde atua um firewall comum e um WAF ( o que é um waf? ) para não trocar as suas responsabilidades.

O WAF olha para o contexto onde a aplicação web está inserida, atuando na camada 7 (aplicação), criando uma barreira de segurança onde ocorrem o filtro, monitoramento e bloqueio (aqui vai ser de acordo com a regra configurada). Já um firewall comum trabalha na camada 3 e 4 (rede e transporte) do modelo OSI olhando mais para o fluxo da rede.

waf x firewall (1).png

Na figura é possível observar onde cada um está inserido, seguindo o fluxo:

  • Chega uma requisição;
  • Se não for HTTP ou HTTPS, encaminha para o serviço requisitado ou faz o bloqueio, de acordo com as regras de INPUT definidas;
  • Se for HTTP ou HTTPS, encaminha para o WAF;
  • O WAF filtra, monitora e caso seja uma requisição segura, envia para a aplicação. Caso não seja uma requisição segura, faz o bloqueio.

Como atuam em camadas distintas e com focos totalmente diferentes, um não substitui o outro, eles se complementam.


Honeypot pode ser um aliado na mitigação

Antes de continuar, é preciso entender o que é um honeypot. Vamos de Wikipédia:

Honeypot é um sistema utilizado para atrair um intruso para um ambiente onde há informações falsas que aparentam ser verdadeiras.

Sabendo o que é honeypot e qual o seu objetivo, é possível facilitar a detecção de ataques com implementações simples. Um invasor sempre fará uso da maior quantidade de ferramentas possíveis para automatizar o processo de exploração e para reduzir o tempo que levaria executando as tarefas de forma manual. Essas ferramentas automatizam a obtenção de campos, o preenchimento e o envio. No entanto, não conseguem identificar a "isca" deixada no código.

Considerando que o ponto de entrada para verificação de alguma vulnerabilidade seja um formulário (exemplo uma página de contato), o invasor vai preencher todos os campos do formulário com algum conteúdo malicioso e enviar requisições em sequência, usando alguma ferramenta ou não. Mesmo não utilizando alguma ferramenta, um honeypot dentro de um formulário é algo difícil de ser detectado.

Bem vamos ao código!

Temos o seguinte código:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">   
    <title>Teste honeypot</title>
    <style type="text/css">
    #um-campo-qualquer {
        display: none;
    }
    </style>
</head>
<body>
    <form action="send.php" method="POST">
        <label>Nome</label><input type="text" name="nome" id="nome" />
        <label>E-mail</label><input type="email" name="email" id="email" />
        <input type="text" name="um-campo-qualquer" id="um-campo-qualquer" />
        <input type="submit" value="Enviar" />
    </form>

</body>
</html>

O nosso campo "um-campo-qualquer" servirá de honeypot. Ele foi criado, mas não está sendo exibido para o usuário, pois o CSS está ocultando.

Um scanner, por exemplo, irá preencher todos os campos e enviar. Aqui que está o segredo: não esperamos que esse campo seja preenchido em requisições normais.

send.php

<?php

//verificamos se houve o envio do formulário
if (!empty($_POST['email'] ?? null)) {

    $honeypot = $_POST['um-campo-qualquer'] ?? null;

    if(!empty($honeypot)){
        //notifica ou cria uma alerta para a equipe de segurança monitorar a atividade suspeita.
        return;
    }
}

Estude eternamente de forma consistente!

É preciso estudar continuamente para entender as mudanças e antecipar as soluções. Um invasor não foca somente em vulnerabilidades conhecidas, de modo geral, é um excelente pesquisador que estuda de forma consistente exatamente para burlar as camadas de segurança. Sistemas sofrem mudanças em todos os níveis periodicamente, seja na versão do PHP ou em uma simples biblioteca. Uma solução aplicada hoje, pode não ser tão útil amanhã.

Criar fluxos de verificação e exploração contínua, ajudam a mitigar as possíveis vulnerabilidades da aplicação. Mas de nada adianta executar os processos da mesma forma. Supostamente, já disse o sábio:

“Insanidade é continuar fazendo sempre a mesma coisa e esperar resultados diferentes” Einstein, Albert.


PHP é robusto e seguro!

A linguagem tem uma comunidade enorme e bastante ativa. Quando é encontrada alguma vulnerabilidade, a resposta com a correção é realizada de forma rápida. A maior deficiência nos dias atuais é a enorme quantidade de sites e sistemas que ainda usam versões antigas do PHP que não tem mais nenhum tipo de atualização para correção de bug ou falha de segurança.

Capturar.png

Acompanhar o tempo de vida das versões é essencial para planejar a migração das aplicações para as versões mais recentes da linguagem.

Em php.net/supported-versions.php é possível acompanhar esse ciclo.

Outro fator que leva a conclusão errônea de que PHP não é seguro, está totalmente voltado com a forma como são escritos os códigos.

Como em qualquer outra grande linguagem, se escrevermos códigos de forma insegura, a aplicação ficará vulnerável. Não tem segredo!

Desenvolvimento seguro é pensar em segurança no momento da concepção da aplicação. Olhar para segurança na última etapa é fazer gestão de vulnerabilidades.

Assim como outros fatores que viram cultura dentro dos times de desenvolvimento de software, segurança deve ser um tema relevante e bem difundido para que deixe de ser algo complementar. Só assim olharemos para segurança como parte essencial. Criar uma cultura forte e duradoura onde o tema seja incluído desde o início é o grande desafio.

É isso!