Tudo bem, basta parar; aqui está o que eu vim até agora
(desculpe, post longo à frente. Seja corajoso, amigo, a jornada valerá a pena)
Combinando os métodos 3 e 4 da postagem original em uma espécie de lista branca 'fuzzy' ou dinâmica, e então - e aqui está o truque - não bloquear IPs não incluídos na lista de permissões, limitando-os ao inferno .
Observe que esta medida serve apenas para frustrar esse tipo muito específico de ataque. Na prática, é claro, funcionaria em combinação com outras abordagens de práticas recomendadas para autenticação: limitação de nome de usuário fixo, limitação por IP, política de senha forte imposta por código, logon de cookie não acelerado, hash todos os equivalentes de senha antes de salvá-los, nunca usando perguntas de segurança etc.
Pressupostos sobre o cenário de ataque
Se um invasor está direcionando nomes de usuário variáveis, a limitação de nosso nome de usuário não é acionada. Se o invasor estiver usando uma botnet ou tiver acesso a um grande intervalo de IPs, nossa limitação de IP será impotente. Se o invasor pré-rastreou nossa lista de usuários (geralmente possível em serviços da web de registro aberto), não podemos detectar um ataque contínuo com base no número de erros de 'usuário não encontrado'. E se aplicarmos uma limitação restritiva em todo o sistema (todos os nomes de usuário, todos os IPs), qualquer ataque desse tipo prejudicará todo o site durante a duração do ataque mais o período de limitação.
Então, precisamos fazer outra coisa.
A primeira parte da contramedida: lista de permissões
O que podemos ter certeza é que o invasor não é capaz de detectar e falsificar dinamicamente os endereços IP de vários milhares de nossos usuários (+). O que torna a lista de permissões viável. Em outras palavras: para cada usuário, armazenamos uma lista dos IPs (com hash) de onde o usuário efetuou o login anteriormente (recentemente).
Portanto, nosso esquema de lista de permissões funcionará como uma 'porta da frente' trancada, na qual um usuário deve estar conectado a partir de um dos seus IPs 'bons' reconhecidos para fazer login. Um ataque de força bruta a essa 'porta da frente' seria praticamente impossível (+).
(+) a menos que o invasor 'seja dono' do servidor, de todas as caixas de nossos usuários ou da própria conexão - e nesses casos, não temos mais um problema de 'autenticação', temos um pull-the genuíno do tamanho de uma franquia situação FUBAR
A segunda parte da contramedida: limitação em todo o sistema de IPs não reconhecidos
Para fazer com que uma lista de permissões funcione para um serviço da Web de registro aberto, em que os usuários trocam de computador com frequência e / ou se conectam a partir de endereços IP dinâmicos, precisamos manter uma 'porta de gato' aberta para usuários que se conectam a partir de IPs não reconhecidos. O truque é projetar essa porta para que as botnets fiquem presas e os usuários legítimos sejam incomodados o menos possível .
No meu esquema, isso é conseguido através da definição de um número máximo muito restritivo de tentativas de logon com falha por IPs não aprovados durante, digamos, um período de 3 horas (pode ser mais sensato usar um período mais curto ou mais longo, dependendo do tipo de serviço) e tornando essa restrição global , ie. para todas as contas de usuário.
Mesmo uma força bruta lenta (1-2 minutos entre tentativas) seria detectada e frustrada de maneira rápida e eficaz usando esse método. Obviamente, uma força bruta realmente lenta ainda pode passar despercebida, mas velocidades muito baixas derrotam o próprio objetivo do ataque da força bruta.
O que espero conseguir com esse mecanismo de limitação é que, se o limite máximo for atingido, nossa 'porta do gato' se fecha por um tempo, mas nossa porta da frente permanece aberta para usuários legítimos que se conectam por meios usuais:
- Conectando-se a partir de um de seus IPs reconhecidos
- Ou usando um cookie de login persistente (de qualquer lugar)
Os únicos usuários legítimos que seriam afetados durante um ataque - ie. enquanto a limitação foi ativada - seriam usuários sem cookies de login persistentes que estavam fazendo login de um local desconhecido ou com um IP dinâmico. Esses usuários não conseguiriam fazer login até que a limitação acabasse (o que poderia levar um tempo, se o invasor mantivesse sua botnet em execução, apesar da limitação).
Para permitir que esse pequeno subconjunto de usuários atravesse a porta do gato selada de outro modo, mesmo enquanto os bots ainda estavam martelando, eu empregaria um formulário de login de 'backup' com um CAPTCHA. Portanto, quando você exibir a mensagem "Desculpe, mas não pode fazer login neste endereço IP no momento", inclua um link que diz " login seguro para backup - SOMENTE PARA HUMANOS ( bots: sem mentir ) ". Brincadeira à parte, quando clicarem nesse link, forneça a eles um formulário de login autenticado pelo reCAPTCHA que ignora a otimização em todo o site. Dessa forma, se eles são humanos E sabem o login + senha correto (e conseguem ler CAPTCHAs), eles nunca terão o serviço negado, mesmo se estiverem se conectando a partir de um host desconhecido e não estiverem usando o cookie de login automático.
Ah, e apenas para esclarecer: Como eu considero os CAPTCHAs geralmente ruins, a opção de login 'backup' só aparece quando a limitação estiver ativa .
Não há como negar que um ataque sustentado como esse ainda constituiria uma forma de ataque DoS, mas com o sistema descrito em vigor, isso afetaria apenas o que eu suspeito ser um pequeno subconjunto de usuários, ou seja, pessoas que não usam o O cookie "lembra-me" E, por acaso, está efetuando login enquanto um ataque está ocorrendo E não está efetuando login em nenhum de seus IPs habituais E que não conseguem ler CAPTCHAs. Somente aqueles que podem dizer não a TODOS esses critérios - especificamente bots e pessoas com deficiência muito azaradas - serão recusados durante um ataque de bot.
EDIT: Na verdade, pensei em uma maneira de permitir que usuários desafiados pelo CAPTCHA passassem durante um 'bloqueio': em vez de ou como um complemento para o login de backup do CAPTCHA, forneça ao usuário a opção de ter um uso único , código de bloqueio específico do usuário enviado para seu e-mail, que ele pode usar para ignorar a limitação. Definitivamente, isso ultrapassa meu limite de 'irritação', mas como é usado apenas como último recurso para um pequeno subconjunto de usuários, e como ainda é melhor do que ser bloqueado na sua conta, seria aceitável.
(Além disso, observe que nada disso acontece se o ataque for menos sofisticado do que a desagradável versão distribuída que eu descrevi aqui. Se o ataque vier de apenas alguns IPs ou apenas de alguns nomes de usuário, ele será frustrado muito antes. e sem consequências em todo o site)
Portanto, essa é a contramedida que implementarei na minha biblioteca de autenticação, uma vez que estou convencido de que é bom e que não há uma solução muito mais simples que eu tenha perdido. O fato é que existem muitas maneiras sutis de fazer coisas erradas em segurança, e não estou acima de fazer suposições falsas ou lógica irremediavelmente falho. Então, por favor, todo e qualquer feedback, crítica e aprimoramento, sutilezas etc. são muito apreciados.