A internet é uma ferramenta indispensável no dia a dia das pessoas. Seja para pagar uma conta, fazer um pedido de entrega ou mesmo enviar a sua declaração do imposto de renda. Devido a isso, muitos criminosos usam artimanhas para conseguir invadir um sistema para benefício próprio. Embora haja métodos extremamente sofisticados para burlar a segurança de um sistema, existe alguns que são comumente explorados e, por incrível de que pareça, são falhas recorrentes em sistemas empresariais.
A Open Worldwide Application Security Project, chamada de OWASP, é uma organização sem fins lucrativos que trabalha no aperfeiçoamento da segurança de softwares. Um de seus trabalhos mais importantes é o Top Ten, que consistem em divulgações periódicas das brechas de segurança mais encontradas em sistemas computacionais.
A seguir, listamos o Top 10 OWASP de 2024:
Broken Access Control
O sistema deve ter controle integral de acesso dos usuários e nunca deve permitir o acesso de algo sem a permissão adequada. Esse é o principal motivo da adoção do princípio de menor privilégio, no qual o usuário só deve ter as permissões estritamente necessárias e seja bloqueado por padrão caso ele não tenha a devida autorização. Quando esse princípio não é respeitado, um usuário pode adicionar, modificar ou deletar dados de forma maliciosa e gerar situações catastróficas.
Um usuário consegue explorar isso modificando a URL, o estado interno da aplicação, a página HTML ou fazendo diretamente as requisições a uma API. Isso também pode ser feito alterando o JWT, os cookies ou campos de um formulário. Uma configuração errada de CORS também pode permitir o acesso a uma API por origens não confiáveis. Se um usuário consegue ver, editar, inserir ou deletar algum dado de outra pessoa, é um forte indício que seu sistema está vulnerável.
Cryptographic Failure
Quando um dado é armazenado ou transferido pela rede, nós precisamos sempre considerar que esse dado pode acessado indevidamente, o que pode gerar exposição de dados sensíveis. Isso inclui desde informações pessoais até dados de contratos, relatórios ou segredos comerciais. Por isso, a criptografia é fundamental para garantir a segurança desses dados.
Em relação a transferência de dados, podemos destacar a importância do TLS para estabelecer uma conexão segura com o cliente como o HTTPS. Um certificado SSL válido é essencial para garantir a comunicação segura. Repito: válido. Não confie em qualquer autoridade certificadora se você não tiver certeza absoluta de que ela é confiável. Acessando uma página pelo computador da empresa? Eu tomaria cuidado, pois não confio nas CA dos computadores da minha empresa se eu não for administrador.
Quanto ao armazenamento, os dados estão criptografados? Qual o nível de segurança desses algoritmos e suas senhas? Há rotação de senhas? Guardar dados sensíveis é uma operação delicada. Se você faz dump do banco de dados de produção no seu notebook, o que poderia acontecer se ele fosse roubado? Se você salva simplesmente a senha dos usuários ou o hash dela sem um salt, você precisa saber que é uma questão de tempo até o desastre.
Injection
const query = "SELECT * FROM USERS WHERE ID = " + id;
Se você já viu isso em algum sistema, saiba que é questão de tempo até o autor ser convidado a se retirar da empresa. Brincadeiras à parte, é um erro comum de programadores inexperientes. A sanitização e a validação dos dados são primordiais, pois nada que vem de fora da API é confiável. Se seu ID é um número, faz sentido armazenar como uma string? Quantas pessoas no mundo tem um nome completo com mais de 1000 caracteres? Quem tem idade negativa, está vivo ou não? Tão ruim como acessar dados de outros usuários, espere o que vai acontecer quando o usuário com o seguinte ID acessar o sistema:
const id = "1; DELETE FROM USERS WHERE 1 = 1; COMMIT; --"
const query = "SELECT * FROM USERS WHERE ID = " + id;
A solução para esse tipo de problema é simples: não reinvente a roda. Confie em um ORM robusto que filtre e escape quaisquer conjunto de caracteres e palavras-chaves ao montar uma consulta. Você não vai conseguir fazer uma solução melhor que uma centena de outros devs. Entretanto, use o ORM direito. Não adianta usar um ORM e usar uma raw query concatenando as strings.
Insecure Design
Injection é um exemplo de implementação não segura. O que seria um design não seguro? Seria um sistema com falha de segurança devido as suas regras de negócios ou ao fluxo do sistema que não poderia ser resolvido mesmo se o código fosse seguro. Vamos para um exemplo:
Suponhamos que um sistema exija o número do CPF e a senha cadastrada para fazer login. Entretanto, usuário nunca entrou no sistema e vai para a tela de cadastro. O sistema pede para o usuário digitar o CPF dele. Como eu garanto que o CPF digitado é dele mesmo? Se eu tenho como consultar algumas informações pessoais dele, é fácil. Basta eu perguntar o nome da mãe dele, o nome da cidade em que ele nasceu e o nome da primeira empresa em que ele trabalho. Simples assim. Ou será que não? Acredito que esse exemplo já deu uma pista do problema. Eu sei o nome da mãe, da cidade de nascimento e o nome da primeira empresa do meu melhor amigo. Consigo o CPF dele? Claro! Precisa de autenticação de biometria facial? Inteligência artificial e uma foto resolve o problema. Nesse caso, por mais seguro que o código fosse, haveria uma brecha de segurança devido ao próprio fluxo de autenticação de um usuário.
Um outro exemplo que ocorre no dia a dia é aquelas promoções relâmpagos incríveis que acabam em menos de 1 segundos. Como é possível alguém comprar tão rápido assim? Lógico que essas compras são feitas por bot, que exploram a ausência de mecanismos de identificação de bots para fazer compras instantâneas prejudicando os consumidores e não gerando o resultado desejado da promoção.
Security Misconfiguration
Há muitos cenários de erros de configurações que acabam no esquecimento e vão para produção.
- Sabe aquela usuário e senha admin/admin que era temporário apenas para a POC? Agora está em produção e ninguém percebeu.
- O framework do sistema já está na versão 6, mas a equipe continua usando a versão 4 porque é muito arriscado atualizar a biblioteca.
- Você precisa acessar o servidor via SSH, HTTP, HTTPS, SFTP além de todas as outras 10 portas que o seu sistema usa. Só liberar todas as portas no firewall que está tranquilo, afinal somente algumas pessoas acessam esse servidor mesmo.
- Para investigar um problema, nada melhor do que fazer o build para produção com o source-map junto ou sem obfuscar o código-fonte.
Se você já fez alguma dessas ações, saiba que seu sistema está em risco. No dia a dia, é comum fazer ajustes temporários que acabam sendo permanentes. Tome cuidao quando precisar fazer algo assim.
Qualquer funcionalidade desnecessária para o sistema deve ser removida e todas as atualizações importantes devem ser realizadas. Além disso, lembre-se:
- Já é hora de ativar aquela analisador de código estático no pipeline.
- O ambiente da develop, staging e production não podem usar as mesmas credenciais.
- Não deixe o usuário ver as tecnologias que o seu sistema usa. Ele não precisa saber que você usa o nginx quando ocorre um 404.
Vulnerable and Outdated Components
Preciso de um componente para drag-and-drop para deixar meu frontend espetacular. Qual biblioteca usar? Temos a biblioteca ABC, com milhares de estrelas, último commit há 2 semanas, vários pull requests relevantes, documentação extensa e código disponível para consultar e modificar. Temos também a biblioteca XYZ que está no tutorial de drag-and-drop simples que eu encontrei na internet, mas foi feita por um único desenvolvedor, último commit há 4 anos, sem readme, partes do código indisponível para consulta e várias dependências ainda mais antigas. Qual biblioteca devo escolher?
Em sistemas empresariais, nem sempre podemos usar as versões mais novas dos softwares, pois precisamos usar as versões mais estáveis ou com suporte de longo prazo. Entretanto, isso não significa que devemos deixar o sistema com as bibliotecas defasadas. Atualize tudo que puder: sistema operacional, softwares, bibliotecas, drivers e aquele seu package-lock.json que está sem commit há anos.
Identification and Authentication Failures
Autenticação de usuários e uma tarefa que exige atenção. O usuário é um dos elos mais fracos quando falamos em sistemas computacionais. Por que ter uma senha complexa quando posso usar algo simples como 19981210? Ou 12345678? Obviamente, não podemos colocar regras infinitas para considerar uma senha suficientemente segura. Então, precisamos de um trade-off: o que podemos exigir do usuário para deixar a senha forte sem fazer o usuário abrir um ticket de senha esquecida toda vez que vai logar no sistema? Não há uma única resposta.
Agora que o usuário tem uma senha boa, você olha o log e percebe que ele tentou logar no sistema 200 vezes em um período de 1 minuto. Esse usuário deve ser muito rápido para digitar a senha, não é? Considere limitar o número de requisições do usuário para evitar ataques de força bruta. Se precisar de um nível de segurança maior, considere usar um segundo fator de segurança (aplicativo de 2FA, mensagem de celular, confirmação por email). Se for um sistema altamente crítico, considere um terceiro fator (biometria).
Software and Data Integrity Failures
Quando baixamos um software, é comum encontrar o hash do binário. Sabe para que ele serve? Para confirmar que o arquivo que foi baixado é confiável. Ferramentas de gerenciamento de pacotes como o NPM e o Maven baixam as dependências de repositórios onlines. Certifique que eles sejam baixando de fontes confiáveis ou hospede o seu próprio repositório de pacotes se for necessário. Utilize TLS para se conectar a esses repositórios.
Além de falhas de segurança externas, não podemos ignorar que a falha pode vir de dentro da própria empresa. Por isso, é fundamental que a equipe tenha a prática de revisão de código, pois os devs mais experientes e, digamos, com mais credibilidade, conseguem se certificar que ninguém está colocando algum código que possa ser uma falha de segurança, seja intencional ou não. Nunca confie no autor de um commit se ele não estiver assinado com a chave privada. Tenha os pipelines de CI/CD bem configurados para não misturar configurações de ambientes distintos. Pense duas vezes antes de importar dados do ambiente de produção nos ambientes de homologação ou desenvolvimento.
Security Logging and Monitoring Failures
Quando falamos de problemas com log, temos algumas possibilidades:
- Logs de eventos do sistema e da API não são monitorados, sendo que seriam essenciais para investigar atividades suspeitas.
- Mensagens ambíguas, pouco claras ou insuficientes.
- Logs armazenados em uma única máquina sem qualquer backup.
- Logs são coletados e armazenados, mas não são usados para nada
Em muitas situações, logs são a única pista para investigar um problema que ocorreu ou ocorre em produção. Por isso, os logs precisam estar estruturados em alguma ferramenta que permita a pesquisa de forma simples para gerar insights para a tomada de decisão.
Vamos supor que, de alguma forma, alguém conseguiu acessar o banco de dados de produção e fez diversas alterações além de extrair diversos relatórios. Quando você descobre isso, seu chefe te pede o máximo de informações para reportar o incidente. Como você vai explicar que não tem nenhum registro do incidente e que isso pode estar ocorrendo há meses ou anos? Por isso, o monitoramento pela equipe de DevSecOps é essencial para identificar atividades suspeitas e tomar as ações necessárias.
Server-Side Request Forgery (SSRF)
A falha SSRF ocorre quando um servidor busca um recurso em outro sistema por uma URL informada pelo cliente, mas não há a validação da URL. Vamos supor que o sistema retorna imagens por meio de uma API. O usuário passa a URL da imagem e o servidor busca no repositório correspondente. Se não houver a validação adequada, o usuário poderia passar um outro endereço para acessar um serviço interno que somente este servidor poderia acessar. Poderia ser, por exemplo, um banco de dados, uma API com dados sigilosos, uma ferramenta de logs, etc.
Para evitar esse tipo de problema, reforçamos novamente um ponto: nunca confie nos dados enviados pelo usuário. Neste caso, é imprescindível que haja validação da entrada para garantir o acesso ao recurso correto. Caso seja diferente, bloqueio o acesso e não esqueça de adicionar isso no log para investigação. Contudo, não faça isso por expressão regular ou uma simples lista, pois os invasores são muito criativos para conseguir contornar essas soluções.
Conclusão
A lista Top 10 OWASP contém alguns dos ataques mais comuns em sistemas na web, mas não inclui todos os possíveis problemas. Diante disso, é fundamental estar atento a novas vulnerabilidades e procurar resolvê-las assim que possível. Além disso, contar com uma equipe de DevSecOps é também aconselhado para que eles monitorem e identifiquem as falhas antes que se tornem tragédias.
Referências
- https://owasp.org/about/
- https://owasp.org/Top10/A01_2021-Broken_Access_Control/
- https://owasp.org/Top10/A02_2021-Cryptographic_Failures/
- https://owasp.org/Top10/A03_2021-Injection/
- https://owasp.org/Top10/A04_2021-Insecure_Design/
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration/
- https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/
- https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/
- https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/
- https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/
- https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/