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.
Alguns passos simples:
Coloque na lista negra certos nomes de usuário comuns e use-os como um honeypot. Admin, convidado, etc ... Não deixe ninguém criar contas com esses nomes; portanto, se alguém tentar fazer login, você sabe que é alguém que está fazendo algo que não deveria.
Verifique se alguém com poder real no site possui uma senha segura. Exija que os administradores / moderadores tenham senhas mais longas com uma mistura de letras, números e símbolos. Rejeite senhas trivialmente simples de usuários regulares com uma explicação.
Uma das coisas mais simples que você pode fazer é dizer às pessoas quando alguém tentou fazer login em sua conta e fornecer um link para relatar o incidente, se não fossem elas. Uma mensagem simples quando eles fazem login, como "Alguém tentou fazer login na sua conta às 04h20, quarta-feira blá blá. Clique aqui se este não for você." Permite manter algumas estatísticas sobre ataques. Você pode intensificar as medidas de monitoramento e segurança se perceber que há um aumento repentino de acessos fraudulentos.
fonte
Se eu entendo o MO dos ataques de força bruta corretamente, um ou mais nomes de usuários são tentados continuamente.
Há duas sugestões que acho que ainda não vi aqui:
Editar : em resposta a comentários sobre um acelerador de nome de usuário: este é um acelerador específico de nome de usuário, independentemente da origem do ataque.
Se o nome de usuário for regulado, mesmo um ataque coordenado de nome de usuário (IP múltiplo, palpite único por IP, mesmo nome de usuário) será capturado. Os nomes de usuário individuais são protegidos pelo acelerador, mesmo que os atacantes estejam livres para tentar outro usuário / passe durante o tempo limite.
Do ponto de vista do invasor, durante o tempo limite, você poderá adivinhar pela primeira vez 100 senhas e descobrir rapidamente uma senha errada por conta. Você pode conseguir adivinhar apenas 50 segundos pelo mesmo período.
Do ponto de vista de uma conta de usuário, ainda é necessário o mesmo número médio de suposições para quebrar a senha, mesmo que as suposições sejam provenientes de várias fontes.
Para os invasores, na melhor das hipóteses, será o mesmo esforço para quebrar 100 contas como uma conta, mas como você não está otimizando em todo o site, pode acelerar o acelerador rapidamente.
Refinamentos extras:
Ideias de interface do usuário (podem não ser adequadas neste contexto), que também podem refinar o acima:
fonte
Existem três fatores de autenticação:
Geralmente, os sites aplicam apenas a política nº 1. Até a maioria dos bancos aplica apenas a política 1. Em vez disso, eles recorrem a uma abordagem "sabe outra coisa" para autenticação de dois fatores. (IE: um usuário sabe sua senha e o nome de solteira da mãe.) Se você puder, uma maneira de adicionar um segundo fator de autenticação não é muito difícil.
Se você pode gerar cerca de 256 caracteres aleatórios, você pode estruturá-lo em uma tabela 16 × 16 e pedir ao usuário para fornecer o valor na tabela da célula A-14, por exemplo. Quando um usuário se inscrever ou alterar sua senha, forneça a tabela e peça para imprimi-la e salvá-la.
A dificuldade dessa abordagem é que, quando um usuário esquece sua senha, como preferir, você não pode simplesmente oferecer o padrão "responda a essa pergunta e coloque uma nova senha", pois isso também é vulnerável à força bruta. Além disso, você não pode redefini-lo e enviar um novo por e-mail, pois o email também pode ser comprometido. (Consulte: Makeuseof.com e seu domínio roubado.)
Outra idéia (que envolve gatinhos) é o que a BOA chama SiteKey (acredito que eles tenham o nome registrado). Resumidamente, você solicita ao usuário que faça o upload de uma imagem ao se registrar e, quando tentarem fazer login, peça para escolher sua imagem dentre 8 ou 15 (ou mais) aleatórias. Portanto, se um usuário faz upload de uma foto do seu gatinho, teoricamente, apenas ele sabe exatamente qual é a imagem deles dentre todos os outros gatinhos (ou flores ou qualquer outra coisa). A única real remuneração que essa abordagem tem é o ataque do homem do meio.
Mais uma ideia (sem gatinhos) é rastrear os IPs com os quais os usuários acessam o sistema e exigir que eles executem autenticação adicional (captcha, escolha um gatinho, escolha uma chave nesta tabela) quando fizerem login em um endereço que não possuem. antes. Além disso, semelhante ao GMail, permite que o usuário visualize de onde efetuou login recentemente.
Editar, nova ideia:
Outra maneira de validar as tentativas de login é verificar se o usuário veio ou não da sua página de login. Você não pode verificar os referenciadores, pois eles podem ser facilmente falsificados. O que você precisa é definir uma chave na var _SESSION quando o usuário visualizar a página de logon e, em seguida, verifique se a chave existe ao enviar suas informações de logon. Se o bot não enviar a partir da página de login, ele não poderá efetuar o login. Você também pode facilitar isso envolvendo o javascript no processo, usando-o para definir um cookie ou adicionando algumas informações ao formulário após o carregamento. Ou você pode dividir o formulário em dois envios diferentes (ou seja, o usuário digita seu nome de usuário, envia e, em uma nova página, insere sua senha e envia novamente.)
A chave, neste caso, é o aspecto mais importante. Um método comum de gerá-los é uma combinação dos dados do usuário, seu IP e a hora em que foram enviados.
fonte
Eu já havia respondido a uma pergunta muito semelhante em Como posso controlar as tentativas de login do usuário em PHP . Reiterarei a solução proposta aqui, pois acredito que muitos de vocês acharão informativo e útil ver algum código real. Lembre-se de que o uso de um CAPTCHA pode não ser a melhor solução devido aos algoritmos cada vez mais precisos usados nos busters CAPTCHA atualmente:
Você não pode simplesmente impedir ataques de DoS encadeando a aceleração para um único IP ou nome de usuário. Inferno, você realmente não pode impedir tentativas de logon de disparo rápido usando esse método.
Por quê? Porque o ataque pode abranger vários IPs e contas de usuário, a fim de ignorar suas tentativas de limitação.
Vi em outro lugar que, idealmente, você deve rastrear todas as tentativas de login com falha no site e associá-las a um carimbo de data / hora, talvez:
Decida sobre alguns atrasos com base no número geral de logins com falha em um determinado período de tempo. Você deve basear isso nos dados estatísticos retirados da sua
failed_logins
tabela, pois eles serão alterados com o tempo, com base no número de usuários e quantos deles poderão recuperar (e digitar) sua senha.Consulte a tabela em todas as tentativas de logon com falha para localizar o número de logins com falha por um determinado período, digamos 15 minutos:
Se o número de tentativas durante o período especificado ultrapassar o seu limite, imponha a limitação ou force todos os usuários a usar um captcha (ou seja, reCaptcha) até que o número de tentativas com falha no período especificado seja menor que o limite.
O uso do reCaptcha em um determinado limite garantiria que um ataque de várias frentes fosse minimizado e os usuários normais do site não experimentariam um atraso significativo por tentativas legítimas de logon com falha. Não posso garantir a prevenção, pois já foi expandido que os CAPTCHA podem ser presos. Existem soluções alternativas, talvez uma variante de "Nomeie este animal", que poderia funcionar muito bem como um substituto.
fonte
Eu tenho que perguntar se você fez uma análise de custo-benefício desse problema; parece que você está tentando se proteger de um invasor com presença na web suficiente para adivinhar várias senhas, enviando talvez de 3 a 5 solicitações por IP (desde que você descartou a limitação de IP). Quanto (aproximadamente) esse tipo de ataque custaria? É mais caro que o valor das contas que você está tentando proteger? Quantas botnets gigantescas querem o que você tem?
A resposta pode ser não - mas, se for, espero que você esteja recebendo ajuda de algum profissional de segurança; a habilidade de programação (e a pontuação do StackOverflow) não se correlacionam fortemente com o conhecimento de segurança.
fonte
Para resumir o esquema de Jens em um diagrama de transição de pseudo-estado / base de regra:
// never throttle
// slow the bots
// humans still welcome
// a correct guess from a bot
Observações:
Essas observações abrangem um tipo diferente de ataque aos que você está tentando combater.
fonte
Parece que você está tentando se defender contra a força bruta distribuída lentamente . Não há muito o que você possa fazer sobre isso. Estamos usando um PKI e sem logins de senha. Isso ajuda, mas se seus clientes encontrarem estações de trabalho de vez em quando, isso não será muito aplicável.
fonte
Disclaimer: Eu trabalho para uma empresa de dois fatores, mas não estou aqui para ligá-lo. Aqui estão algumas observações.
Os cookies podem ser roubados com XSS e vulns do navegador. Os usuários geralmente alteram os navegadores ou limpam seus cookies.
Os endereços IP de origem são simultaneamente dinamicamente variáveis e falsificáveis.
Captcha é útil, mas não autentica um ser humano específico.
Vários métodos podem ser combinados com sucesso, mas o bom gosto certamente está em ordem.
A complexidade da senha é boa, qualquer coisa baseada em senha depende criticamente de senhas com entropia suficiente. IMHO, uma senha forte anotada em um local físico seguro é melhor do que uma senha fraca na memória. As pessoas sabem como avaliar a segurança dos documentos em papel muito melhor do que sabem como calcular a entropia efetiva no nome de seus cães quando usadas como senha para três sites diferentes. Considere oferecer aos usuários a capacidade de imprimir uma página grande ou pequena cheia de códigos de uso único.
Questões de segurança como "qual era o seu mascote do ensino médio" são principalmente uma outra forma ruim de "algo que você conhece", a maioria delas é facilmente adivinhada ou direta no domínio público.
Como você observou, refrear as tentativas de logon com falha é um compromisso entre impedir ataques de força bruta e a facilidade de DoSing de uma conta. Políticas de bloqueio agressivas podem refletir uma falta de confiança na entropia de senha.
Pessoalmente, não vejo o benefício de impor a expiração de senha em um site de qualquer maneira. O invasor obtém sua senha uma vez. Ele pode alterá-la e obedecer a essa política da maneira mais fácil possível. Talvez um benefício seja que o usuário perceba mais cedo se o invasor alterar a senha da conta. Melhor ainda seria se o usuário fosse notificado de alguma forma antes do invasor obter acesso. Mensagens como "N tentativas com falha desde o último login" são úteis nesse sentido.
A melhor segurança vem de um segundo fator de autenticação que está fora de banda em relação ao primeiro. Como você disse, os tokens de hardware no "algo que você tem" são ótimos, mas muitos (nem todos) têm uma sobrecarga de administrador real associada à sua distribuição. Não conheço nenhuma solução biométrica "algo que você seja" que seja boa para sites. Algumas soluções de dois fatores funcionam com provedores abertos, outras possuem SDKs PHP / Perl / Python.
fonte
Minha recomendação mais alta é simplesmente garantir que você mantenha os usuários informados sobre tentativas incorretas de login em suas contas - os usuários provavelmente levarão a força de sua senha muito mais a sério se forem apresentados com evidências de que alguém está realmente tentando acessar sua conta .
Na verdade, peguei alguém que invadiu a conta do myspace do meu irmão porque eles tentaram acessar a conta do Gmail que eu configurei para ele e usei o recurso 'redefinir minha senha por e-mail' ... que foi para a minha caixa de entrada.
fonte
Que tal exigir uma senha de uso único antes de inserir a senha normal? Isso tornaria muito óbvio que alguém estava atacando antes de ter muitas oportunidades de adivinhar a senha principal?
Mantenha uma contagem / taxa global de falhas de login - este é o indicador de um ataque - durante um ataque, seja mais rigoroso quanto a falhas de login, por exemplo, bana IPs mais rapidamente.
fonte
Não acredito que haja uma resposta perfeita, mas estaria inclinado a abordá-la com base na tentativa de confundir os robôs se um ataque for detectado.
Em cima da minha mente:
Alterne para uma tela de login alternativa. Possui vários espaços em branco de nome de usuário e senha que realmente aparecem, mas apenas um deles está no lugar certo. Os nomes dos campos são ALEATÓRIOS - uma chave de sessão é enviada junto com a tela de login, e o servidor pode descobrir quais são os campos. Se você tiver êxito ou falhar, ele será descartado para que você não possa tentar um ataque de repetição - se você rejeitar a senha, eles obterão um novo ID de sessão.
Qualquer formulário enviado com dados em um campo errado é assumido como sendo de um robô - o logon falha, ponto final e esse IP é regulado. Verifique se os nomes dos campos aleatórios nunca correspondem aos nomes dos campos legítimos, para que alguém que use algo que se lembre de senhas não seja enganado.
Em seguida, que tal um tipo diferente de captcha: você tem uma série de perguntas que não causam problemas para um ser humano. No entanto, eles não são aleatórios. Quando o ataque começa, todos recebem a pergunta 1. Após uma hora, a pergunta 1 é descartada, para nunca mais ser usada novamente e todos recebem a pergunta 2 e assim por diante.
O invasor não pode tentar fazer o download do banco de dados para colocar em seu robô devido à natureza descartável das perguntas. Ele precisa enviar novas instruções para sua botnet dentro de uma hora para ter a capacidade de fazer qualquer coisa.
fonte
Como várias pessoas incluíram o CAPTCHA como um mecanismo humano de fallback, estou adicionando uma pergunta anterior do StackOverflow e um tópico sobre a eficácia do CAPTCHA.
O reCaptcha foi quebrado / hackeado / OCR'd / derrotado / quebrado?
O uso do CAPTCHA não limita as melhorias de sua otimização e outras sugestões, mas acho que o número de respostas que incluem o CAPTCHA como substituto deve considerar os métodos baseados em humanos disponíveis para as pessoas que desejam violar a segurança.
fonte
Você também pode acelerar com base na força da senha de um usuário.
Quando um usuário registra ou altera sua senha, você calcula uma classificação de força para sua senha, digamos entre 1 e 10.
Algo como "senha" marca 1, enquanto "c6eqapRepe7et * Awr @ ch" pode ter 9 ou 10 e quanto maior a pontuação, mais tempo leva para a aceleração entrar em ação.
fonte
A primeira resposta que geralmente ouvi ao fazer esta pergunta é alterar as portas, mas esqueça isso e desative o IPv4. Se você permitir apenas clientes de redes IPv6, não estará mais orando por uma simples varredura de rede e os atacantes recorrerão a pesquisas de DNS. Não execute no mesmo endereço do seu Apache (AAAA) / Sendmail (MX-> AAAA) / o que você deu a todos (AAAA). Verifique se a sua zona não pode ser xferd. Aguarde, você está permitindo que sua zona seja baixada por alguém?
Se os bots encontrarem o servidor configurando novos nomes de host, basta acrescentar algumas semelhanças aos nomes de host e alterar seu endereço. Deixe os nomes antigos e até os nomes de configuração ** honeypot para que a rede de bots atinja o tempo limite.
** Teste seus registros reversos (PTR) (em ip6.arpa.) Para ver se eles podem ser usados para zerar os on / 4 que possuem registros VS / 4 que não. IE Normalmente, o ip6.arpa teria ~ 32 "." S em um endereço, mas tentar com os últimos desaparecidos pode iludir os blocos de rede que possuem registros VS outros que não. Se você levar isso adiante, é possível pular grandes porções do espaço de endereço.
Na pior das hipóteses, os usuários terão que configurar um túnel IPv6, não é como se tivessem que acessar VPN em uma DMZ ... Embora se pergunte por que essa não é a primeira opção.
O Kerberos também é legal, mas o IMHO LDAP explode (o que há de errado com o NISPlus? Li que a Sun decidiu que os usuários queriam LDAP e, por isso, abandonaram o NIS +). O Kerberos funciona bem sem LDAP ou NIS, apenas com o gerenciamento de usuários host por host. O uso do Kerberos fornece uma PKI fácil de usar, se não automatizada.
fonte
Um pouco tarde aqui, mas eu estava pensando, assumindo um caso difícil - o invasor usa muitos IPs aleatórios, nomes de usuário aleatórios e uma senha aleatória selecionada dentre uma lista dos 10.000 mais populares.
Uma coisa que você pode fazer, especialmente se o sistema parecer estar sob ataque, pois há muitas tentativas erradas de senha no sistema e, especialmente, se a senha é de baixa entropia, é fazer uma pergunta secundária, como os nomes de seus pais, por exemplo . Se um invasor acertar um milhão de contas tentando a senha 'password1', há uma boa chance de obter muito, mas suas chances de acertar os nomes reduziriam drasticamente o sucesso.
fonte