10 Vulnerabilidades de segurança na Web mais comuns

Publicados: 2022-03-11

Para muitas empresas, é somente após a ocorrência de uma violação de segurança que as práticas recomendadas de segurança na Web se tornam uma prioridade. Durante meus anos trabalhando como profissional de segurança de TI, tenho visto repetidas vezes o quão obscuro o mundo dos problemas de segurança do desenvolvimento da Web pode ser para muitos de meus colegas programadores.

Uma abordagem eficaz às ameaças à segurança da Web deve, por definição, ser proativa e defensiva. Para esse fim, este post visa estimular uma mentalidade de segurança, esperançosamente injetando no leitor uma dose saudável de paranóia.

Em particular, este guia se concentra em 10 armadilhas de segurança da Web comuns e significativas que você deve conhecer, incluindo recomendações sobre como elas podem ser mitigadas. O foco está nas 10 principais vulnerabilidades da Web identificadas pelo Open Web Application Security Project (OWASP), uma organização internacional sem fins lucrativos cujo objetivo é melhorar a segurança de software em todo o mundo.

Um exemplo de algumas vulnerabilidades comuns da web que ninguém quer enfrentar.

Uma pequena cartilha de segurança cibernética antes de começarmos – autenticação e autorização

Ao falar com outros programadores e profissionais de TI, muitas vezes encontro confusão em relação à distinção entre autorização e autenticação. E, claro, o fato de a abreviação auth ser frequentemente usada para ambos ajuda a agravar essa confusão comum. Essa confusão é tão comum que talvez esse problema deva ser incluído neste post como “Common Web Vulnerability Zero”.

Então, antes de prosseguirmos, vamos esclarecer a distinção entre esses dois termos:

  • Autenticação: Verificar se uma pessoa é (ou pelo menos aparenta ser) um usuário específico, desde que tenha fornecido corretamente suas credenciais de segurança (senha, respostas a perguntas de segurança, digitalização de impressões digitais, etc.).
  • Autorização: Confirmar que um determinado usuário tem acesso a um recurso específico ou tem permissão para realizar uma determinada ação.

Dito de outra forma, autenticação é saber quem é uma entidade, enquanto autorização é saber o que uma determinada entidade pode fazer. Com isso em mente, vamos entrar nos 10 principais problemas de segurança na Internet.

Erro comum de segurança da Web nº 1: falhas de injeção

As falhas de injeção resultam de uma falha clássica em filtrar entradas não confiáveis. Isso pode acontecer quando você passa dados não filtrados para o servidor SQL (injeção de SQL), para o navegador (XSS – falaremos sobre isso mais tarde), para o servidor LDAP (injeção de LDAP) ou qualquer outro lugar. O problema aqui é que o invasor pode injetar comandos nessas entidades, resultando em perda de dados e seqüestro dos navegadores dos clientes.

Qualquer coisa que seu aplicativo receba de fontes não confiáveis ​​deve ser filtrada, de preferência de acordo com uma lista de permissões. Você quase nunca deve usar uma lista negra, pois acertar é muito difícil e geralmente fácil de contornar. Os produtos de software antivírus geralmente fornecem exemplos excelentes de listas negras com falhas. A correspondência de padrões não funciona.

Prevenção: A boa notícia é que a proteção contra a injeção é “simplesmente” uma questão de filtrar sua entrada adequadamente e pensar se uma entrada pode ser confiável. Mas a má notícia é que toda entrada precisa ser filtrada adequadamente, a menos que seja inquestionavelmente confiável (mas o ditado “nunca diga nunca” vem à mente aqui).

Em um sistema com 1.000 entradas, por exemplo, filtrar com sucesso 999 delas não é suficiente, pois isso ainda deixa um campo que pode servir como a cura de Aquiles para derrubar seu sistema. E você pode pensar que colocar um resultado de consulta SQL em outra consulta é uma boa ideia, pois o banco de dados é confiável, mas se o perímetro não for, a entrada vem indiretamente de caras com más intenções. Isso é chamado de injeção de SQL de segunda ordem caso você esteja interessado.

Como a filtragem é muito difícil de fazer corretamente (como criptografia), o que costumo aconselhar é confiar nas funções de filtragem do seu framework: elas comprovadamente funcionam e são minuciosamente examinadas. Se você não usa frameworks, realmente precisa pensar muito se não usá-los realmente faz sentido no contexto de segurança do seu servidor. 99% das vezes não.

Erro comum de segurança da Web nº 2: autenticação quebrada

Esta é uma coleção de vários problemas que podem ocorrer durante a autenticação quebrada, mas nem todos têm origem na mesma causa raiz.

Supondo que alguém ainda queira lançar seu próprio código de autenticação em 2014 (o que você está pensando?), eu desaconselho isso. É extremamente difícil acertar, e há uma infinidade de possíveis armadilhas, apenas para citar algumas:

  1. A URL pode conter o ID da sessão e vazá-lo no cabeçalho do referenciador para outra pessoa.
  2. As senhas podem não ser criptografadas no armazenamento ou em trânsito.
  3. Os ids de sessão podem ser previsíveis, portanto, obter acesso é trivial.
  4. A fixação da sessão pode ser possível.
  5. Sequestro de sessão pode ser possível, timeouts não implementados corretamente ou usando HTTP (sem segurança SSL), etc…

Prevenção: A maneira mais direta de evitar essa vulnerabilidade de segurança da Web é usar uma estrutura. Você pode implementar isso corretamente, mas o primeiro é muito mais fácil. Caso você queira criar seu próprio código, seja extremamente paranóico e eduque-se sobre quais são as armadilhas. Há muito poucos.

Erro comum de segurança da Web nº 3: script entre sites (XSS)

Esta é uma falha de sanitização de entrada bastante difundida (essencialmente um caso especial de erro comum nº 1). Um invasor fornece tags JavaScript ao seu aplicativo da Web na entrada. Quando essa entrada for devolvida ao usuário sem limpeza, o navegador do usuário a executará. Pode ser tão simples quanto criar um link e persuadir um usuário a clicar nele, ou pode ser algo muito mais sinistro. No carregamento da página, o script é executado e, por exemplo, pode ser usado para postar seus cookies para o invasor.

Prevenção: Existe uma solução simples de segurança na web: não retorne tags HTML ao cliente. Isso tem o benefício adicional de se defender contra injeção de HTML, um ataque semelhante em que o invasor injeta conteúdo HTML simples (como imagens ou flash players invisíveis) – não de alto impacto, mas certamente irritante (“por favor, faça-o parar!”). Normalmente, a solução é simplesmente converter todas as entidades HTML, para que <script> seja retornado como &lt;script&gt; . O outro método de sanitização frequentemente empregado é usar expressões regulares para remover tags HTML usando expressões regulares em < e > , mas isso é perigoso, pois muitos navegadores interpretam HTML severamente quebrado muito bem. Melhor converter todos os caracteres para suas contrapartes com escape.

Relacionado: 9 perguntas essenciais da entrevista de segurança do sistema

Erro comum de segurança da Web nº 4: referências a objetos diretos inseguros

Este é um caso clássico de confiar na entrada do usuário e pagar o preço de uma vulnerabilidade de segurança resultante. Uma referência de objeto direta significa que um objeto interno, como um arquivo ou chave de banco de dados, é exposto ao usuário. O problema com isso é que o invasor pode fornecer essa referência e, se a autorização não for aplicada (ou for quebrada), o invasor poderá acessar ou fazer coisas das quais deveria ser impedido.

Por exemplo, o código tem um módulo download.php que lê e permite que o usuário baixe os arquivos, usando um parâmetro CGI para especificar o nome do arquivo (por exemplo, download.php?file=something.txt ). Por engano ou por preguiça, o desenvolvedor omitiu a autorização do código. O invasor agora pode usar isso para baixar quaisquer arquivos de sistema aos quais o usuário executando o PHP tenha acesso, como o próprio código do aplicativo ou outros dados deixados no servidor, como backups. Uh-oh.

Outro exemplo comum de vulnerabilidade é uma função de redefinição de senha que depende da entrada do usuário para determinar a senha que estamos redefinindo. Depois de clicar no URL válido, um invasor pode simplesmente modificar o campo de username de usuário no URL para dizer algo como “admin”.

Aliás, esses dois exemplos são coisas que eu mesmo vi aparecendo muitas vezes “na natureza”.

Prevenção: execute a autorização do usuário de forma adequada e consistente e coloque as opções na lista de permissões. Na maioria das vezes, porém, todo o problema pode ser evitado armazenando dados internamente e não confiando que eles sejam passados ​​do cliente por meio de parâmetros CGI. As variáveis ​​de sessão na maioria das estruturas são adequadas para esse propósito.

Erro comum de segurança da Web nº 5: configuração incorreta de segurança

Na minha experiência, servidores e aplicativos da Web que foram configurados incorretamente são muito mais comuns do que aqueles que foram configurados corretamente. Talvez isso porque não faltam maneiras de estragar tudo. Alguns exemplos:

  1. Executando o aplicativo com depuração habilitada em produção.
  2. Ter a listagem de diretórios habilitada no servidor, que vaza informações valiosas.
  3. Executando software desatualizado (pense em plugins do WordPress, antigo PhpMyAdmin).
  4. Ter serviços desnecessários em execução na máquina.
  5. Não alterando chaves e senhas padrão. (Acontece com muito mais frequência do que você imagina!)
  6. Revelar informações de tratamento de erros para os invasores, como rastreamentos de pilha.

Prevenção: Tenha um bom processo de “compilação e implantação” (de preferência automatizado), que possa executar testes na implantação. A solução de configuração incorreta de segurança do pobre homem são ganchos pós-commit, para evitar que o código saia com senhas padrão e/ou material de desenvolvimento embutido.

Erro comum de segurança da Web nº 6: exposição de dados confidenciais

Essa vulnerabilidade de segurança da Web é sobre proteção de criptografia e recursos. Os dados confidenciais devem ser criptografados o tempo todo, inclusive em trânsito e em repouso. Sem exceções. Informações de cartão de crédito e senhas de usuário nunca devem viajar ou ser armazenadas sem criptografia, e as senhas devem sempre ser criptografadas. Obviamente, o algoritmo de criptografia/hashing não deve ser fraco – em caso de dúvida, os padrões de segurança da Web recomendam AES (256 bits ou mais) e RSA (2048 bits ou mais).

E, embora seja desnecessário dizer que os IDs de sessão e os dados confidenciais não devem estar viajando nas URLs e os cookies confidenciais devem ter o sinalizador de segurança ativado, isso é muito importante e não pode ser enfatizado demais.

Prevenção:

  • Em trânsito: Use HTTPS com um certificado adequado e PFS (Perfect Forward Secrecy). Não aceite nada em conexões não HTTPS. Tenha a bandeira segura nos cookies.

  • No armazenamento: Isso é mais difícil. Em primeiro lugar, você precisa diminuir sua exposição. Se você não precisar de dados confidenciais, destrua-os. Os dados que você não possui não podem ser roubados. Nunca armazene informações de cartão de crédito, pois você provavelmente não quer ter que lidar com a conformidade com PCI. Inscreva-se com um processador de pagamento como Stripe ou Braintree. Em segundo lugar, se você tiver dados confidenciais de que realmente precisa, armazene-os criptografados e certifique-se de que todas as senhas tenham hash. Para hash, o uso de bcrypt é recomendado. Se você não usa bcrypt, eduque-se sobre salga e tabelas de arco-íris.

E correndo o risco de afirmar o óbvio, não armazene as chaves de criptografia ao lado dos dados protegidos . É como guardar sua bicicleta com um cadeado que contém a chave. Proteja seus backups com criptografia e mantenha suas chaves muito privadas. E claro, não perca as chaves!

Erro comum de segurança da Web nº 7: controle de acesso de nível de função ausente

Isso é simplesmente uma falha de autorização. Isso significa que quando uma função é chamada no servidor, a autorização adequada não foi realizada. Muitas vezes, os desenvolvedores confiam no fato de que o lado do servidor gerou a interface do usuário e pensam que a funcionalidade que não é fornecida pelo servidor não pode ser acessada pelo cliente. Não é tão simples assim, pois um invasor sempre pode forjar solicitações para a funcionalidade “oculta” e não será impedido pelo fato de a interface do usuário não tornar essa funcionalidade facilmente acessível. Imagine que há um painel /admin e o botão só está presente na interface do usuário se o usuário for realmente um administrador. Nada impede um invasor de descobrir essa funcionalidade e usá-la incorretamente se a autorização estiver ausente.

Prevenção: No lado do servidor, a autorização deve sempre ser feita. Sim, sempre. Nenhuma exceção ou vulnerabilidade resultará em problemas sérios.

Erro comum de segurança da Web nº 8: falsificação de solicitação entre sites (CSRF)

Este é um bom exemplo de um vice-ataque confuso pelo qual o navegador é enganado por alguma outra parte e faz uso indevido de sua autoridade. Um site de terceiros, por exemplo, pode fazer com que o navegador do usuário faça uso indevido de sua autoridade para fazer algo pelo invasor.

No caso de CSRF, um site de terceiros emite solicitações ao site de destino (por exemplo, seu banco) usando seu navegador com seus cookies/sessão. Se você estiver logado em uma guia da página inicial do seu banco, por exemplo, e eles estiverem vulneráveis ​​a esse ataque, outra guia pode fazer com que seu navegador faça uso indevido de suas credenciais em nome do invasor, resultando no problema do deputado confuso. O substituto é o navegador que usa indevidamente sua autoridade (cookies de sessão) para fazer algo que o invasor o instrui a fazer.

Considere este exemplo:

A atacante Alice quer aliviar a carteira de Todd, transferindo parte de seu dinheiro para ela. O banco de Todd é vulnerável a CSRF. Para enviar dinheiro, Todd precisa acessar a seguinte URL:

http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243

Depois que essa URL é aberta, uma página de sucesso é apresentada a Todd e a transferência é feita. Alice também sabe que Todd frequentemente visita um site sob seu controle em blog.aliceisawesome.com, onde ela coloca o seguinte trecho:

<img src=http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243 width=0 height=0 />

Ao visitar o site de Alice, o navegador de Todd pensa que Alice se vincula a uma imagem e automaticamente emite uma solicitação HTTP GET para buscar a imagem, mas isso na verdade instrui o banco de Todd a transferir $ 1.500 para Alice.

Aliás, além de demonstrar a vulnerabilidade CSRF, este exemplo também demonstra a alteração do estado do servidor com uma solicitação HTTP GET idempotente que é em si uma vulnerabilidade séria. As solicitações HTTP GET devem ser idempotentes (seguras), o que significa que não podem alterar o recurso que é acessado. Nunca, jamais, use métodos idempotentes para alterar o estado do servidor.

Curiosidade: CSRF também é o método que as pessoas usavam para rechear biscoitos no passado até que os afiliados ficassem mais sábios.

Prevenção: Armazene um token secreto em um campo de formulário oculto que seja inacessível no site de terceiros. É claro que você sempre precisa verificar esse campo oculto. Alguns sites também pedem sua senha ao modificar configurações confidenciais (como seu e-mail de lembrete de senha, por exemplo), embora eu suspeite que isso esteja lá para evitar o uso indevido de suas sessões abandonadas (em um cibercafé, por exemplo).

Erro comum de segurança da Web nº 9: usando componentes com vulnerabilidades conhecidas

O título diz tudo. Eu classificaria novamente isso como mais um problema de manutenção/implantação. Antes de incorporar um novo código, faça alguma pesquisa, possivelmente alguma auditoria. Usar o código que você obteve de uma pessoa aleatória no GitHub ou em algum fórum pode ser muito conveniente, mas não está isento de risco de grave vulnerabilidade de segurança na web.

Já vi muitos casos, por exemplo, em que sites se tornaram proprietários (ou seja, onde um estranho obtém acesso administrativo a um sistema), não porque os programadores fossem estúpidos, mas porque um software de terceiros permaneceu sem correção por anos em produção. Isso está acontecendo o tempo todo com plugins do WordPress, por exemplo. Se você acha que eles não encontrarão sua instalação oculta do phpmyadmin , deixe-me apresentá-lo ao dirbuster.

A lição aqui é que o desenvolvimento de software não termina quando o aplicativo é implantado. Deve haver documentação, testes e planos sobre como mantê-lo e mantê-lo atualizado, especialmente se ele contiver componentes de terceiros ou de código aberto.

Prevenção:

  • Precaução no exercício. Além de obviamente ter cuidado ao usar esses componentes, não seja um codificador de copiar e colar. Inspecione cuidadosamente o pedaço de código que você está prestes a colocar em seu software, pois ele pode estar quebrado além do reparo (ou, em alguns casos, intencionalmente mal-intencionado – ataques de segurança da Web às vezes são involuntariamente convidados dessa maneira).

  • Mantenha-se atualizado. Certifique-se de estar usando as versões mais recentes de tudo em que você confia e tenha um plano para atualizá-las regularmente. Pelo menos assine um boletim informativo de novas vulnerabilidades de segurança relacionadas ao produto.

Erro comum de segurança da Web nº 10: redirecionamentos e encaminhamentos não validados

Este é mais uma vez um problema de filtragem de entrada. Suponha que o site de destino tenha um módulo redirect.php que receba uma URL como parâmetro GET . A manipulação do parâmetro pode criar uma URL em targetsite.com que redireciona o navegador para malwareinstall.com . Quando o usuário vir o link, ele verá targetsite.com/blahblahblah , que o usuário acredita ser confiável e seguro para clicar. Mal sabem eles que isso realmente os transferirá para uma página de malware (ou qualquer outra maliciosa). Como alternativa, o invasor pode redirecionar o navegador para targetsite.com/deleteprofile?confirm=1 .

Vale a pena mencionar que o preenchimento de entrada definida pelo usuário não sanitizada em um cabeçalho HTTP pode levar à injeção de cabeçalho, o que é muito ruim.

Prevenção: As opções incluem:

  • Não faça redirecionamentos (eles raramente são necessários).
  • Tenha uma lista estática de locais válidos para redirecionar.
  • Coloque na lista de permissões o parâmetro definido pelo usuário, mas isso pode ser complicado.

Epílogo

Espero ter conseguido agradar um pouco seu cérebro com este post e apresentar uma dose saudável de paranóia e conscientização sobre vulnerabilidades de segurança do site.

O principal argumento aqui é que práticas de software antigas existem por um motivo e o que se aplicava no passado para estouros de buffer, ainda se aplica a strings em conserva em Python hoje. Os protocolos de segurança ajudam você a escrever (mais) programas corretos, aos quais todos os programadores devem aspirar.

Por favor, use este conhecimento com responsabilidade e não teste páginas sem permissão!

Para obter mais informações e ataques mais específicos do lado do servidor, consulte: https://www.owasp.org/index.php/Category:Attack.

Comentários sobre este post e seus conselhos de mitigação são bem-vindos e apreciados. Postagens futuras relacionadas estão planejadas, particularmente sobre a questão de vulnerabilidades de segurança de TI de negação de serviço distribuída (DDoS) e da velha escola (não da web). Se você tiver uma solicitação específica sobre o tipo de proteção da Web sobre a qual escrever, sinta-se à vontade para me contatar diretamente em [email protected].

Aqui está a segurança do site! Saúde.

Relacionado:
  • Tutorial JSON Web Token: Um Exemplo em Laravel e AngularJS
  • Desempenho e eficiência: trabalhando com HTTP/3