Cybersegurança · Gestão de riscos · Modelagem de ameaças · Backend
Corrigir minhas próprias descobertas: um plano de remediação, classificado por risco
O meu modelo de ameaça deste formulário de contato do site encontrou quatro fraquezas. Nem todas as descobertas merecem a mesma urgência. Aqui está como eu as classifiquei por probabilidade e impacto, como planejo corrigir cada uma e por que estou escolhendo aceitar uma delas.
Em o meu modelo de ameaça deste formulário de contato do site, eu terminei com quatro fraquezas que encontrei no meu próprio design. Encontrar problemas é a parte fácil. A parte mais difícil é decidir o que corrigir primeiro, como e o que não corrigir.
Este post é a segunda parte: um pequeno plano de remediação real.

Como eu as classifiquei
Uma maneira simples de comparar riscos é fazer duas perguntas sobre cada um:
- Probabilidade: quão provável é que essa fraqueza seja explorada ou cause danos?
- Impacto: se acontecer, quão ruim é e para quem?
A matriz acima é o meu próprio julgamento, não uma medição. Isso é normal: a maioria das avaliações de risco reais é julgamento informado, escrito para que os outros possam questioná-lo. O valor está em tornar o raciocínio visível.
1. Mensagens mantidas para sempre: corrigir primeiro
O risco. Cada mensagem enviada através do formulário permanece no banco de dados indefinidamente. Cada uma contém um nome, um endereço de e-mail e o que a pessoa escolheu me contar. Se o banco de dados fosse exposto, por meio de uma credencial vazada ou um erro meu, tudo o que foi enviado seria exposto com ele.
Por que ela é classificada em primeiro lugar. O impacto afeta outras pessoas, que confiaram em mim com seus detalhes. E a probabilidade de que algum armazenamento de dados, em algum lugar, seja eventualmente exposto ao longo de muitos anos não é pequena. Dados que você não mantém não podem vazar.
A correção. Um trabalho agendado que exclui mensagens mais antigas que um período fixo. Os Cloudflare Workers suportam disparadores cron, então o mesmo Worker que recebe mensagens pode executar uma consulta diária DELETE FROM messages WHERE created_at < …. Doze meses parecem certos: suficientemente longos para seguir uma conversa, suficientemente curtos para limitar o que uma violação poderia revelar. Isso também traz o site mais perto do princípio de limitação de armazenamento na Lei de Proteção de Dados de Gana, 2012 (Lei 843).
2. 'unsafe-inline' na política de script
O risco. A Política de Segurança de Conteúdo do site permite scripts inline. A CSP é uma rede de segurança contra scripting entre sites (XSS): se um atacante algum dia conseguisse injetar um script em uma página, uma política estrita o impediria de executar. Com 'unsafe-inline', a rede tem um buraco exatamente no lugar errado.
Por que ela é classificada em segundo lugar. A probabilidade é baixa: o site é estático e não exibe conteúdo submetido pelo usuário, então não há um ponto de injeção óbvio hoje. Mas o impacto de um XSS bem-sucedido em todos os visitantes seria alto, e a defesa em profundidade significa não confiar em "não há bug hoje".
A correção. Substituir 'unsafe-inline' por um hash para cada script inline. No momento da compilação, calcular o hash SHA-256 de cada script inline e listar esses hashes na política. O navegador então executa apenas scripts cujo conteúdo exato eu aprovou. Como o site é estático, os hashes mudam apenas quando eu mudo um script, então isso pode ser automatizado na compilação.
3. Uma limitação de taxa que pode ser ultrapassada
O risco. O limite de cinco mensagens por hora por IP é armazenado em Cloudflare KV, que é eventualmente consistente, e o código lê o contador e, em seguida, o escreve como duas etapas separadas. Uma explosão de solicitações enviadas em paralelo pode ler a mesma contagem antiga e ultrapassar ligeiramente o limite.
Por que ele ocupa o terceiro lugar. É fácil de acionar, mas o impacto é pequeno: algumas mensagens de spam extras que ainda têm que passar pela verificação do bot Turnstile. Para um formulário de contato, um limite aproximado é aceitável. Ele não seria aceitável para algo como tentativas de login.
A solução. Mover o contador para algo com atualizações atômicas: seja a limitação de taxa integrada do Cloudflare para Workers, ou um Durable Object, que processa solicitações para uma chave determinada uma de cada vez. Qualquer um remove a corrida.
4. IPs compartilhados compartilham um limite: aceitar, documentar, monitorar
O risco. Muitas redes móveis colocam um grande número de usuários atrás de um pequeno pool de endereços IP públicos compartilhados. Em tal rede, um usuário abusivo poderia usar o limite horário para pessoas inocentes que compartilham o endereço.
Por que estou aceitando. Toda alternativa tem um custo. Limitar por endereço de e-mail é fácil de evitar com endereços fabricados. Remover o limite de IP enfraqueceria a proteção contra inundações. Aumentar o limite muito permitiria que mais spam passasse. Dado que um visitante bloqueado pode simplesmente tentar novamente mais tarde ou me enviar um e-mail diretamente, o dano é pequeno.
O que “aceitar” significa. Aceitar um risco é uma decisão legítima, mas apenas quando é consciente e registrada. Então, estou escrevendo isso aqui, com o raciocínio, e revisitarei se eu algum dia vir visitantes reais sendo bloqueados. Se isso fosse um serviço para milhares de usuários móveis, em vez de um formulário de contato pessoal, eu o classificaria muito mais alto.
O que este exercício me ensinou
Duas lições:
- Não toda descoberta é urgente. Classificar por probabilidade e impacto me impediu de gastar meu tempo na solução técnica mais interessante (a corrida de limitação de taxa) antes daquela que realmente protege as pessoas (excluir dados antigos).
- “Corrigir”, “mitigar” e “aceitar” são todos resultados válidos, desde que a escolha seja deliberada. Um plano de segurança que afirma corrigir tudo geralmente é um que não olhou com atenção suficiente.
Atualizarei este post à medida que cada solução for implantada.
Discorda com minha classificação? Gostaria de saber por quê.
