O guia definitivo para autenticação de site baseado em formulário [fechado]

5372

Autenticação baseada em formulário para sites

Acreditamos que o Stack Overflow não deve ser apenas um recurso para perguntas técnicas muito específicas, mas também para diretrizes gerais sobre como resolver variações em problemas comuns. "Autenticação baseada em formulário para sites" deve ser um ótimo tópico para esse experimento.

Deve incluir tópicos como:

  • Como fazer login
  • Como sair
  • Como permanecer logado
  • Gerenciando cookies (incluindo configurações recomendadas)
  • Criptografia SSL / HTTPS
  • Como armazenar senhas
  • Usando perguntas secretas
  • Funcionalidade esquecida de nome de usuário / senha
  • Uso de nonces para impedir falsificações de solicitação entre sites (CSRF)
  • OpenID
  • Caixa de seleção "Lembrar-me"
  • Preenchimento automático do navegador de nomes de usuário e senhas
  • URLs secretos ( URL público protegido por resumo)
  • Verificando a força da senha
  • Validação de email
  • e muito mais sobre autenticação baseada em formulário ...

Não deve incluir coisas como:

  • Funções e autorização
  • Autenticação básica HTTP

Ajude-nos por:

  1. Sugestões de subtópicos
  2. Submetendo bons artigos sobre este assunto
  3. Editando a resposta oficial
Michiel de Mare
fonte
52
Por que excluir a autenticação básica HTTP? Ele pode funcionar em formulários HTML via Ajax: peej.co.uk/articles/http-auth-with-html-forms.html
system PAUSE
55
A autenticação básica HTTP tem a propriedade de ser (comparativamente) difícil fazer um navegador esquecer. Também é terrivelmente inseguro se você não o usa com SSL para proteger a conexão (por exemplo, HTTPS).
Donal Fellows
24
Eu acho que seria vale a pena falar sessões (incluindo fixação e seqüestro) cookies (o seguro e http apenas bandeiras) HTTP baseado SSO
symcbean
29
O HttpOnlysinalizador de cookie super útil , que evita o roubo de cookies baseado em JavaScript (um subconjunto de ataques XSS), também deve ser mencionado em algum lugar.
27560 Alan
80
Uau. Respostas longas, dezenas de votos positivos para algumas delas, mas ninguém menciona o erro comum de servir formulários de login por HTTP. Eu até discuti com pessoas que disseram "mas ele envia para https: // ..." e só ficou em branco quando perguntei se eles tinham certeza de que um invasor não reescreveu a página não criptografada na qual o formulário foi veiculado .
dzuelke

Respostas:

3764

PARTE I: Como entrar

Vamos supor que você já sabe como criar um formulário HTML de login + senha que POST coloca os valores em um script no servidor para autenticação. As seções abaixo tratarão de padrões para uma autenticação prática sólida e como evitar as armadilhas de segurança mais comuns.

Para HTTPS ou não para HTTPS?

A menos que a conexão já esteja segura (ou seja, tunelada através de HTTPS usando SSL / TLS), os valores do seu formulário de login serão enviados em texto não criptografado, permitindo que qualquer pessoa que esteja ouvindo a linha entre o navegador e o servidor da Web possa ler os logins à medida que passam através. Esse tipo de escutas telefônicas é feito rotineiramente pelos governos, mas, em geral, não abordaremos os fios 'de propriedade' além de dizer o seguinte: basta usar HTTPS.

Em essência, a única maneira prática de se proteger contra escutas telefônicas / detecção de pacotes durante o login é usando HTTPS ou outro esquema de criptografia baseada em certificado (por exemplo, TLS ) ou um esquema de resposta a desafios comprovado e testado (por exemplo, o Diffie-Hellman SRP baseado em Qualquer outro método pode ser facilmente contornado por um invasor que escuta.

Obviamente, se você quiser ser um pouco impraticável, também poderá empregar algum tipo de esquema de autenticação de dois fatores (por exemplo, o aplicativo Google Authenticator, um livro de códigos físico 'estilo de guerra fria' ou um dongle gerador de chave RSA). Se aplicado corretamente, isso pode funcionar mesmo com uma conexão não segura, mas é difícil imaginar que um desenvolvedor esteja disposto a implementar autenticação de dois fatores, mas não SSL.

(Não) Role seu próprio criptografia / hash JavaScript

Dado o custo percebido (embora agora evitável ) e a dificuldade técnica de configurar um certificado SSL em seu site, alguns desenvolvedores são tentados a lançar seus próprios esquemas de hash ou criptografia no navegador para evitar a transmissão de logins de texto não criptografado por um fio não seguro.

Embora este seja um pensamento nobre, é essencialmente inútil (e pode ser uma falha de segurança ), a menos que seja combinado com um dos itens acima - ou seja, proteger a linha com criptografia forte ou usar uma resposta de desafio testada e comprovada mecanismo (se você não souber o que é isso, saiba que é um dos mais difíceis de provar, mais difíceis de projetar e mais difíceis de implementar conceitos em segurança digital).

Embora seja verdade que o hash da senha possa ser eficaz contra a divulgação de senhas , ele é vulnerável a ataques de repetição, ataques / sequestros do tipo Man-In-The-Middle (se um invasor puder injetar alguns bytes na sua página HTML não segura antes de atingir seu objetivo). navegador, eles podem simplesmente comentar o hash no JavaScript) ou ataques de força bruta (desde que você esteja entregando ao invasor o nome de usuário, a senha salt e a hash).

CAPTCHAS contra a humanidade

O CAPTCHA visa impedir uma categoria específica de ataque: dicionário automatizado / tentativa e erro de força bruta sem operador humano. Não há dúvida de que essa é uma ameaça real; no entanto, existem maneiras de lidar com isso sem problemas que não exigem um CAPTCHA, esquemas de otimização de login do lado do servidor especificamente projetados adequadamente - discutiremos mais adiante.

Saiba que as implementações de CAPTCHA não são criadas da mesma forma; eles geralmente não são solucionáveis ​​por humanos, a maioria deles é realmente ineficaz contra bots, todos eles são ineficazes contra mão-de-obra barata no terceiro mundo (de acordo com a OWASP , a taxa atual de oficinas é de US $ 12 por 500 testes) e algumas implementações podem ser tecnicamente ilegal em alguns países (consulte a OWASP Authentication Cheat Sheet ). Se você precisar usar um CAPTCHA, use o reCAPTCHA do Google , pois é difícil para OCR por definição (já que usa digitalizações de livros já classificadas incorretamente por OCR) e tenta muito ser amigável.

Pessoalmente, costumo achar CAPTCHAS irritante e usá-los apenas como último recurso quando um usuário não loga várias vezes e os atrasos de limitação são atingidos no máximo. Isso raramente acontece o suficiente para ser aceitável e fortalece o sistema como um todo.

Armazenamento de senhas / verificação de logins

Finalmente, isso pode ser um conhecimento comum depois de todos os hacks e vazamentos de dados de usuários altamente divulgados que vimos nos últimos anos, mas é preciso dizer: Não armazene senhas em texto não criptografado em seu banco de dados. Os bancos de dados dos usuários são rotineiramente hackeados, vazados ou colhidos através da injeção de SQL e, se você estiver armazenando senhas brutas em texto sem formatação, é um jogo instantâneo para sua segurança de login.

Portanto, se você não pode armazenar a senha, como verifica se a combinação de logon + senha POSTADA no formulário de logon está correta? A resposta é o hash usando uma função de derivação de chave . Sempre que um novo usuário é criado ou uma senha é alterada, você pega a senha e a executa através de um KDF, como Argon2, bcrypt, scrypt ou PBKDF2, transformando a senha de texto não criptografado ("correcthorsebatterystaple") em uma cadeia longa e de aparência aleatória , que é muito mais seguro para armazenar em seu banco de dados. Para verificar um logon, execute a mesma função de hash na senha digitada, desta vez passando no salt e compare a cadeia de hash resultante com o valor armazenado em seu banco de dados. Argônio2, bcrypt e scrypt já armazenam o sal com o hash. Confira este artigo em sec.stackexchange para obter informações mais detalhadas.

A razão pela qual um sal é usado é que o hash por si só não é suficiente - você deve adicionar o chamado 'salt' para proteger o hash contra as tabelas do arco-íris . Um salt impede efetivamente que duas senhas que correspondam exatamente sejam armazenadas com o mesmo valor de hash, impedindo que todo o banco de dados seja verificado em uma execução, se um invasor estiver executando um ataque de adivinhação de senha.

Um hash criptográfico não deve ser usado para armazenamento de senhas porque as senhas selecionadas pelo usuário não são fortes o suficiente (ou seja, geralmente não contêm entropia suficiente) e um ataque de suposição de senha pode ser concluído em um tempo relativamente curto por um invasor com acesso aos hashes. É por isso que os KDFs são usados ​​- eles efetivamente "esticam a chave" , o que significa que toda suposição de senha que um invasor faz causa várias repetições do algoritmo de hash, por exemplo, 10.000 vezes, o que faz com que o invasor adivinhe a senha 10.000 vezes mais devagar.

Dados da sessão - "Você está logado como Spiderman69"

Depois que o servidor verifica o login e a senha no banco de dados do usuário e encontra uma correspondência, o sistema precisa de uma maneira de lembrar que o navegador foi autenticado. Esse fato só deve ser armazenado no lado do servidor nos dados da sessão.

Se você não estiver familiarizado com os dados da sessão, veja como ele funciona: Uma única sequência gerada aleatoriamente é armazenada em um cookie expirado e usada para referenciar uma coleção de dados - os dados da sessão - armazenados no servidor. Se você estiver usando uma estrutura MVC, isso sem dúvida já será tratado.

Se possível, verifique se o cookie da sessão tem os sinalizadores seguro e HTTP Only definidos quando enviados ao navegador. O sinalizador HttpOnly fornece alguma proteção contra o cookie que está sendo lido através do ataque XSS. O sinalizador seguro garante que o cookie seja enviado apenas de volta via HTTPS e, portanto, protege contra ataques de detecção de rede. O valor do cookie não deve ser previsível. Quando um cookie referenciando uma sessão inexistente é apresentado, seu valor deve ser substituído imediatamente para evitar a fixação da sessão .

PARTE II: Como permanecer logado - a infame caixa de seleção "Remember Me"

Cookies de login persistentes (funcionalidade "lembre-se de mim") são uma zona de perigo; por um lado, são totalmente tão seguros quanto os logons convencionais quando os usuários entendem como lidar com eles; e, por outro lado, eles representam um enorme risco de segurança nas mãos de usuários descuidados, que podem usá-los em computadores públicos e esquecer de fazer logout, e que podem não saber o que são os cookies do navegador ou como excluí-los.

Pessoalmente, gosto de logins persistentes para os sites que visito regularmente, mas sei como lidar com eles com segurança. Se você acredita que seus usuários sabem o mesmo, use logons persistentes com a consciência limpa. Caso contrário - bem, você pode se inscrever na filosofia de que os usuários que são descuidados com suas credenciais de login criaram isso caso fossem invadidos. Não é como se estivéssemos na casa de nossos usuários e arrancássemos todas as anotações do Post-It com senhas que estavam alinhadas na borda de seus monitores.

Claro, alguns sistemas não pode dar ao luxo de ter quaisquer contas invadidas; para esses sistemas, não há como justificar a existência de logins persistentes.

Se você decidir implementar cookies de login persistentes, é assim que você faz:

  1. Primeiro, reserve um tempo para ler o artigo da Paragon Initiative sobre o assunto. Você precisará acertar vários elementos, e o artigo explica muito bem cada um deles.

  2. E apenas para reiterar uma das armadilhas mais comuns, NÃO ARMAZENE O BOLINHO DE LOGIN PERSISTENTE (TOKEN) NA SUA BASE DE DADOS, APENAS UM HASH! O token de logon é equivalente à senha; portanto, se um invasor colocar as mãos em seu banco de dados, ele poderá usar os tokens para efetuar login em qualquer conta, como se fossem combinações de logon e senha de texto não criptografado. Portanto, use o hash (de acordo com https://security.stackexchange.com/a/63438/5002, um hash fraco funcionará bem para esse propósito) ao armazenar tokens de login persistentes.

PARTE III: Usando perguntas secretas

Não implemente 'perguntas secretas' . O recurso 'perguntas secretas' é um antipadrão de segurança. Leia o artigo do link número 4 da lista DEVE LER. Você pode perguntar a Sarah Palin sobre isso, depois do Yahoo! a conta de email foi hackeada durante uma campanha presidencial anterior porque a resposta para sua pergunta de segurança foi ... "Wasilla High School"!

Mesmo com perguntas especificadas pelo usuário, é altamente provável que a maioria dos usuários escolha:

  • Uma pergunta secreta 'padrão', como o nome de solteira da mãe ou o animal de estimação favorito

  • Uma simples trivialidade que qualquer pessoa poderia extrair de seu blog, perfil do LinkedIn ou similar

  • Qualquer pergunta que seja mais fácil de responder do que adivinhar sua senha. Qual, para qualquer senha decente, é toda pergunta que você pode imaginar

Em conclusão, as questões de segurança são inerentemente inseguras em praticamente todas as suas formas e variações e não devem ser empregadas em um esquema de autenticação por qualquer motivo.

A verdadeira razão pela qual as perguntas de segurança ainda existem na natureza é que elas economizam convenientemente o custo de algumas chamadas de suporte de usuários que não podem acessar seus emails para obter um código de reativação. Isso às custas da segurança e da reputação de Sarah Palin. Vale a pena? Provavelmente não.

PARTE IV: Funcionalidade de senha esquecida

Eu já mencionei por que você nunca deve usar perguntas de segurança para lidar com senhas de usuário esquecidas / perdidas; Também não é necessário dizer que você nunca deve enviar aos usuários por email suas senhas reais. Existem pelo menos mais duas armadilhas comuns demais para evitar neste campo:

  1. Não redefina uma senha esquecida para uma senha forte gerada automaticamente - essas senhas são notoriamente difíceis de lembrar, o que significa que o usuário deve alterá-las ou anotá-las - digamos, em um Post-It amarelo brilhante na borda do monitor. Em vez de definir uma nova senha, permita que os usuários escolham uma nova imediatamente - e é isso que eles querem fazer de qualquer maneira. (Uma exceção a isso pode ser se os usuários estiverem usando universalmente um gerenciador de senhas para armazenar / gerenciar senhas que normalmente seriam impossíveis de lembrar sem anotá-las).

  2. Sempre faça o hash do código / token da senha perdida no banco de dados. NOVAMENTE , esse código é outro exemplo de Senha equivalente, portanto, DEVE ser feito um hash no caso de um invasor colocar as mãos em seu banco de dados. Quando um código de senha perdida for solicitado, envie o código de texto sem formatação para o endereço de e-mail do usuário, faça o hash, salve o hash no seu banco de dados - e jogue fora o original . Assim como uma senha ou um token de login persistente.

Uma observação final: sempre verifique se sua interface para inserir o 'código de senha perdida' é pelo menos tão segura quanto o próprio formulário de login, ou um invasor simplesmente usará isso para obter acesso. Certifique-se de gerar 'códigos de senha perdidos' muito longos (por exemplo, 16 caracteres alfanuméricos com distinção entre maiúsculas e minúsculas) é um bom começo, mas considere adicionar o mesmo esquema de otimização que você faz para o próprio formulário de login.

PARTE V: Verificando a força da senha

Primeiro, você deve ler este pequeno artigo para verificar a realidade: As 500 senhas mais comuns

Ok, talvez a lista não seja a lista canônica das senhas mais comuns em qualquer sistema em qualquer lugar , mas é uma boa indicação de quão mal as pessoas escolherão suas senhas quando não houver uma política aplicada. Além disso, a lista parece assustadoramente próxima de casa quando você a compara às análises publicamente disponíveis de senhas roubadas recentemente.

Portanto: sem requisitos mínimos de força de senha, 2% dos usuários usam uma das 20 principais senhas mais comuns. Significado: se um invasor receber apenas 20 tentativas, uma em cada 50 contas no seu site poderá ser quebrada.

Para impedir isso, é necessário calcular a entropia de uma senha e aplicar um limite. A publicação especial 800-63 do Instituto Nacional de Padrões e Tecnologia (NIST) tem um conjunto de sugestões muito boas. Isso, quando combinado com uma análise de layout de dicionário e teclado (por exemplo, 'qwertyuiop' é uma senha incorreta), pode rejeitar 99% de todas as senhas mal selecionadas em um nível de 18 bits de entropia. Simplesmente calcular a força da senha e mostrar um medidor de força visual para um usuário é bom, mas insuficiente. A menos que seja imposto, muitos usuários provavelmente o ignorarão.

E, para uma visão refrescante da facilidade de uso de senhas de alta entropia, o Password Strength xkcd de Randall Munroe é altamente recomendado.

Utilize a API Fui Pwned de Troy Hunt para verificar senhas de usuários contra senhas comprometidas em violações de dados públicos.

PARTE VI: Muito Mais - Ou: Evitando Tentativas de Login Rápido

Primeiro, dê uma olhada nos números: Velocidades de recuperação de senha - Quanto tempo sua senha ficará em pé

Se você não tiver tempo para examinar as tabelas nesse link, veja a lista delas:

  1. Não leva praticamente tempo para quebrar uma senha fraca, mesmo se você a estiver quebrando com um ábaco

  2. Praticamente não leva tempo para decifrar uma senha alfanumérica de 9 caracteres, caso não seja sensível a maiúsculas e minúsculas

  3. Não leva praticamente tempo para decifrar uma senha intrincada, com letras e números e letras maiúsculas e minúsculas, se tiver menos de 8 caracteres (um PC de mesa pode pesquisar em todo o espaço de teclas até 7 caracteres em uma questão). de dias ou até horas)

  4. No entanto, levaria uma quantidade excessiva de tempo para quebrar até mesmo uma senha de 6 caracteres, se você estivesse limitado a uma tentativa por segundo!

Então, o que podemos aprender com esses números? Bem, mas podemos nos concentrar na parte mais importante: o fato de impedir um grande número de tentativas sucessivas de login rápido (ou seja, o ataque de força bruta ) realmente não é tão difícil. Mas impedi-lo corretamente não é tão fácil quanto parece.

De um modo geral, você tem três opções eficazes contra ataques de força bruta (e ataques de dicionário, mas como você já está empregando uma política forte de senhas, elas não devem ser um problema) :

  • Apresente um CAPTCHA após N tentativas fracassadas (irritante como o inferno e muitas vezes ineficaz - mas estou me repetindo aqui)

  • Bloquear contas e exigir verificação de e-mail após N tentativas fracassadas (este é um ataque de negação de serviço esperando para acontecer)

  • E, finalmente, a limitação de login : ou seja, definir um atraso de tempo entre as tentativas após N tentativas fracassadas (sim, os ataques de DoS ainda são possíveis, mas pelo menos são muito menos prováveis ​​e muito mais complicados de executar).

Prática recomendada nº 1: um pequeno atraso que aumenta com o número de tentativas com falha, como:

  • 1 tentativa falhada = sem atraso
  • 2 tentativas com falha = atraso de 2 s
  • 3 tentativas com falha = atraso de 4 s
  • 4 tentativas com falha = atraso de 8 s
  • 5 tentativas com falha = atraso de 16 s
  • etc.

O DoS que atacar esse esquema seria muito impraticável, pois o tempo de bloqueio resultante é um pouco maior que a soma dos tempos de bloqueio anteriores.

Para esclarecer: O atraso não é um atraso antes de retornar a resposta ao navegador. É mais como um tempo limite ou refratário durante o qual tentativas de login para uma conta específica ou para um endereço IP específico não serão aceitas ou avaliadas. Ou seja, credenciais corretas não retornarão em um logon bem-sucedido e credenciais incorretas não acionarão um aumento de atraso.

Prática recomendada nº 2: um atraso médio que entra em vigor após N tentativas fracassadas, como:

  • 1-4 tentativas com falha = sem atraso
  • 5 tentativas com falha = atraso de 15 a 30 minutos

DoS atacando esse esquema seria bastante impraticável, mas certamente factível. Além disso, pode ser relevante observar que um atraso tão longo pode ser muito irritante para um usuário legítimo. Usuários esquecidos vão gostar de você.

Prática recomendada nº 3: combinando as duas abordagens - um atraso fixo e curto que entra em vigor após N tentativas fracassadas, como:

  • 1-4 tentativas com falha = sem atraso
  • 5+ tentativas com falha = atraso de 20 s

Ou, um atraso crescente com um limite superior fixo, como:

  • 1 tentativa falhada = atraso de 5 s
  • 2 tentativas com falha = atraso de 15 s
  • 3+ tentativas com falha = atraso de 45 s

Esse esquema final foi retirado das sugestões de melhores práticas da OWASP (link 1 da lista DEVER-LER) e deve ser considerado uma boa prática, mesmo que seja reconhecidamente do lado restritivo.

Como regra geral, no entanto, eu diria: quanto mais forte for sua política de senha, menos você precisará corrigir os atrasos nos usuários. Se você precisar de senhas fortes (alfanuméricas com distinção entre maiúsculas e minúsculas + símbolos e números obrigatórios) com mais de 9 caracteres, poderá fornecer aos usuários de 2 a 4 tentativas de senha sem atraso antes de ativar a regulagem.

O DoS que atacar esse esquema final de limitação de login seria muito impraticável. E, como toque final, sempre permita a passagem de logons persistentes (cookies) (e / ou um formulário de login verificado pelo CAPTCHA), para que os usuários legítimos nem se demorem enquanto o ataque estiver em andamento . Dessa forma, o ataque DoS muito impraticável se torna um ataque extremamente impraticável.

Além disso, faz sentido executar uma otimização mais agressiva nas contas de administrador, pois esses são os pontos de entrada mais atraentes

PARTE VII: Ataques Distribuídos de Força Bruta

Além disso, invasores mais avançados tentarão burlar a limitação de logon 'espalhando suas atividades':

  • Distribuindo as tentativas em uma botnet para impedir a sinalização de endereço IP

  • Em vez de escolher um usuário e tentar as 50.000 senhas mais comuns (que não podem, por causa de nossa limitação), eles escolherão a senha mais comum e tentarão contra 50.000 usuários. Dessa forma, eles não apenas evitam medidas de tentativas máximas como CAPTCHAs e limitação de login, mas também aumentam suas chances de sucesso, pois a senha mais comum número 1 é muito mais provável que o número 49.995

  • Espaçando as solicitações de login para cada conta de usuário, digamos, com 30 segundos de diferença, para se esgueirar sob o radar

Aqui, a melhor prática seria registrar o número de logons com falha, em todo o sistema , e usar uma média de execução da frequência de login incorreto do seu site como base para um limite superior que você impõe a todos os usuários.

Abstrato demais? Deixe-me reformular:

Digamos que seu site teve uma média de 120 logins inválidos por dia nos últimos 3 meses. Usando isso (média de execução), seu sistema pode definir o limite global para 3 vezes isso - ou seja. 360 tentativas com falha ao longo de um período de 24 horas. Então, se o número total de tentativas com falha em todas as contas exceder esse número em um dia (ou melhor ainda, monitorar a taxa de aceleração e disparar em um limite calculado), ele ativará a otimização de logon em todo o sistema - significando pequenos atrasos para TODOS os usuários (ainda, com exceção dos logins de cookies e / ou logons CAPTCHA de backup).

Também publiquei uma pergunta com mais detalhes e uma discussão realmente boa de como evitar pitfals complicados em combater ataques distribuídos de força bruta

PARTE VIII: Autenticação de dois fatores e provedores de autenticação

As credenciais podem ser comprometidas, seja por explorações, senhas sendo anotadas e perdidas, laptops com chaves roubadas ou usuários inserindo logins em sites de phishing. Os logins podem ser protegidos ainda mais com autenticação de dois fatores, que usa fatores fora de banda, como códigos de uso único recebidos de uma ligação telefônica, mensagem SMS, aplicativo ou dongle. Vários provedores oferecem serviços de autenticação de dois fatores.

A autenticação pode ser completamente delegada a um serviço de logon único, onde outro provedor lida com a coleta de credenciais. Isso leva o problema a um terceiro confiável. Google e Twitter fornecem serviços SSO baseados em padrões, enquanto o Facebook fornece uma solução proprietária semelhante.

Links obrigatórios sobre autenticação na Web

  1. Guia da OWASP para autenticação / OWASP Authentication Cheat Sheet
  2. Prós e contras da autenticação de clientes na Web (artigo de pesquisa do MIT muito legível)
  3. Wikipedia: cookie HTTP
  4. Perguntas de conhecimento pessoal para autenticação de fallback: perguntas de segurança na era do Facebook (artigo de pesquisa de Berkeley muito legível)
Jens Roland
fonte
67
Bem, eu realmente não concordo com a parte do Captcha, sim, o Captchas é irritante e pode ser quebrado (exceto recaptcha, mas isso dificilmente pode ser resolvido por humanos!), Mas é exatamente como dizer não usar um filtro de spam, porque ele menos de 0,1% de falsos negativos .. este site muito usa Captchas, eles não são perfeitos, mas eles cortaram uma quantidade considerável de spam e não há simplesmente nenhuma boa alternativa para eles
Waleed Eissa
235
@ Jeff: Lamento saber que você tem problemas com a minha resposta. Eu não sabia que havia um debate sobre o Meta sobre essa resposta, eu teria editado de bom grado se você me pedisse. E apagar meus posts apenas apagado 1200 reputação da minha conta, o que dói :(
Jens Roland
13
"Depois de enviar os tokens de autenticação, o sistema precisa lembrar que você foi autenticado - esse fato só deve ser armazenado nos servidores nos dados da sessão. Um cookie pode ser usado para fazer referência aos dados da sessão". Não é bem assim. Você pode (e deve, para servidores sem estado!) Usar um cookie assinado criptograficamente. Isso é impossível de falsificar, não amarra os recursos do servidor e não precisa de sessões complicadas ou outras travessuras.
Martin Probst
12
"um PC de mesa pode pesquisar no espaço de teclado completo até 7 caracteres em menos de 90 dias" Uma máquina com uma GPU recente pode pesquisar no espaço de 7 caracteres completo em menos de 1 dia. Uma GPU de primeira linha pode gerenciar 1 bilhão de hashes por segundo. golubev.com/hashgpu.htm Isso leva a algumas conclusões sobre o armazenamento de senhas que não são endereçadas diretamente.
Frank fazendeiro
9
Estou proteção CSRF surpreso não foi mencionado ...
Flukey
418

Artigo definitivo

Enviando credenciais

A única maneira prática de enviar credenciais 100% com segurança é usando SSL . Usar JavaScript para hash a senha não é seguro. Armadilhas comuns para o hash de senha do lado do cliente:

  • Se a conexão entre o cliente e o servidor não estiver criptografada, tudo o que você faz estará vulnerável a ataques intermediários . Um invasor pode substituir o javascript recebido para interromper o hash ou enviar todas as credenciais para o servidor, ouvir as respostas do cliente e personificar os usuários perfeitamente, etc.
  • A senha com hash recebida pelo servidor é menos segura se você não fizer um trabalho redundante adicional no servidor.

Há outro método seguro chamado SRP , mas é patenteado (embora seja licenciado gratuitamente ) e existem poucas boas implementações disponíveis.

Armazenando Senhas

Nunca armazene senhas como texto simples no banco de dados. Nem mesmo se você não se importa com a segurança do seu próprio site. Suponha que alguns de seus usuários reutilizem a senha da conta bancária online. Portanto, armazene a senha com hash e jogue fora a original. E verifique se a senha não aparece nos logs de acesso ou nos aplicativos. A OWASP recomenda o uso do Argon2 como sua primeira escolha para novas aplicações. Se isso não estiver disponível, PBKDF2 ou scrypt deve ser usado. E finalmente, se nenhuma das opções acima estiver disponível, use bcrypt.

Hashes por si só também são inseguros. Por exemplo, senhas idênticas significam hashes idênticos - isso torna as tabelas de pesquisa de hash uma maneira eficaz de quebrar muitas senhas de uma só vez. Em vez disso, armazene o hash salgado . Um salt é uma string anexada à senha antes do hash - use outro salt (aleatório) por usuário. O salt é um valor público, portanto, você pode armazená-los com o hash no banco de dados. Veja aqui para mais informações.

Isso significa que você não pode enviar ao usuário suas senhas esquecidas (porque você só possui o hash). Não redefina a senha do usuário, a menos que você o tenha autenticado (os usuários devem provar que são capazes de ler os emails enviados para o endereço de email armazenado (e validado).)

Questões de segurança

As perguntas de segurança são inseguras - evite usá-las. Por quê? Qualquer coisa que uma pergunta de segurança faça, uma senha será melhor. Leia a PARTE III: Usando perguntas secretas na resposta de @Jens Roland aqui neste wiki.

Cookies de sessão

Depois que o usuário efetua login, o servidor envia ao usuário um cookie de sessão. O servidor pode recuperar o nome de usuário ou ID do cookie, mas ninguém mais pode gerar esse cookie (mecanismos de explicação do TODO).

Os cookies podem ser invadidos : eles são tão seguros quanto o restante da máquina do cliente e outras comunicações. Eles podem ser lidos a partir do disco, detectados no tráfego da rede, levantados por um ataque de script entre sites, phishing de um DNS envenenado, para que o cliente envie seus cookies para os servidores errados. Não envie cookies persistentes. Os cookies devem expirar no final da sessão do cliente (o navegador fecha ou sai do seu domínio).

Se você deseja registrar automaticamente seus usuários, pode definir um cookie persistente, mas deve ser diferente de um cookie de sessão completa. Você pode definir um sinalizador adicional de que o usuário efetuou login automaticamente e precisa efetuar login real para operações confidenciais. Isso é popular entre os sites de compras que desejam oferecer uma experiência de compra personalizada e contínua, mas ainda protegem seus detalhes financeiros. Por exemplo, quando você volta para visitar a Amazon, eles mostram uma página que parece que você está logado, mas quando você faz um pedido (ou altera seu endereço de entrega, cartão de crédito etc.), eles solicitam que você confirme sua senha.

Os sites financeiros, como bancos e cartões de crédito, por outro lado, possuem apenas dados confidenciais e não devem permitir o login automático ou o modo de baixa segurança.

Lista de recursos externos

Michiel de Mare
fonte
1
Dada a recente vulnerabilidade do MITM em torno dos certificados SSL assinados ( blog.startcom.org/?p=145 ), uma combinação de SSL e algum tipo de autenticação de resposta ao desafio (existem alternativas ao SRP) provavelmente é uma solução melhor.
21411 Kevin Loney
muitas dessas coisas são situacionais. costumo não usar cookies de sessão. os cookies serem seqüestrados quase sempre são culpa dos servidores. man in the middle / packet sniffing Arent que comum
Shawn
Pacote BCrypt Nuget: nuget.org/List/Packages/BCrypt
Fabian Vilers
1
Nota 1 sobre esta resposta: é um rascunho, para ser editado como um wiki. Se você pode editar isso, é bem-vindo.
Peter Mortensen
SRP é específico para a presença de vários partidos se eu entendi bem
Webwoman
162

Primeiro, há uma forte ressalva de que essa resposta não é a mais adequada para essa pergunta exata. Definitivamente não deve ser a melhor resposta!

Vou mencionar o BrowserID proposto pela Mozilla (ou talvez mais precisamente, o Verified Email Protocol ) no espírito de encontrar um caminho de atualização para melhores abordagens de autenticação no futuro.

Vou resumir desta maneira:

  1. A Mozilla é uma organização sem fins lucrativos com valores que se alinham bem ao encontrar boas soluções para esse problema.
  2. A realidade hoje é que a maioria dos sites usa autenticação baseada em formulário
  3. A autenticação baseada em formulário tem uma grande desvantagem, que aumenta o risco de phishing . Os usuários são solicitados a inserir informações confidenciais em uma área controlada por uma entidade remota, em vez de em uma área controlada por seu agente de usuário (navegador).
  4. Como os navegadores são confiáveis ​​implicitamente (toda a idéia de um agente de usuário é agir em nome do usuário), eles podem ajudar a melhorar essa situação.
  5. A principal força que impede o progresso aqui é o impasse de implantação . As soluções devem ser decompostas em etapas que proporcionem algum benefício incremental por conta própria.
  6. O método descentralizado mais simples para expressar uma identidade incorporada à infraestrutura da Internet é o nome de domínio.
  7. Como um segundo nível de expressão de identidade, cada domínio gerencia seu próprio conjunto de contas.
  8. O formulário “ @domínio da conta ” é conciso e é suportado por uma ampla gama de protocolos e esquemas de URI. Esse identificador é, obviamente, o mais universalmente reconhecido como um endereço de email.
  9. Os provedores de email já são os principais provedores de identidade on-line de fato. Os fluxos de redefinição de senha atuais geralmente permitem que você assuma o controle de uma conta se puder provar que controla o endereço de email associado à conta.
  10. O Verified Email Protocol foi proposto para fornecer um método seguro, com base na criptografia de chave pública, para otimizar o processo de comprovação ao domínio B de que você possui uma conta no domínio A.
  11. Para navegadores que não suportam o Verified Email Protocol (atualmente todos eles), o Mozilla fornece uma correção que implementa o protocolo no código JavaScript do lado do cliente.
  12. Para serviços de email que não suportam o Verified Email Protocol, o protocolo permite que terceiros atuem como intermediários confiáveis, afirmando que eles verificaram a propriedade de uma conta por um usuário. Não é desejável ter um grande número desses terceiros; esse recurso destina-se apenas a permitir um caminho de atualização e é muito preferido que os serviços de email forneçam essas afirmações.
  13. A Mozilla oferece seu próprio serviço para agir como um terceiro confiável. Os Provedores de Serviços (ou seja, Confiantes) que implementam o Verified Email Protocol podem optar por confiar nas afirmações da Mozilla ou não. O serviço da Mozilla verifica a propriedade da conta dos usuários usando os meios convencionais de enviar um email com um link de confirmação.
  14. Os prestadores de serviços podem, é claro, oferecer esse protocolo como uma opção, além de qualquer outro (s) método (s) de autenticação que desejarem oferecer.
  15. Um grande benefício da interface do usuário procurado aqui é o "seletor de identidade". Quando um usuário visita um site e escolhe se autenticar, seu navegador mostra uma seleção de endereços de email (“pessoal”, “trabalho”, “ativismo político” etc.) que eles podem usar para se identificar no site.
  16. Outro grande benefício da interface do usuário que está sendo procurado como parte desse esforço é ajudar o navegador a saber mais sobre a sessão do usuário - em quem está conectado atualmente, principalmente - para que ele possa ser exibido no chrome do navegador.
  17. Devido à natureza distribuída desse sistema, evita o bloqueio de sites importantes como Facebook, Twitter, Google etc. Qualquer pessoa pode possuir seu próprio domínio e, portanto, atuar como seu próprio provedor de identidade.

Isso não é estritamente "autenticação baseada em formulário para sites". Mas é um esforço para fazer a transição da norma atual de autenticação baseada em formulário para algo mais seguro: autenticação suportada por navegador.

Charlie
fonte
3
O link do BrowserID está morto
Mehdi Bounya
O projeto parece ter sido empolgado ... veja en.wikipedia.org/wiki/Mozilla_Persona
Jeff Olson
138

Eu apenas pensei em compartilhar essa solução que eu achei que estava funcionando bem.

Eu chamo de Campo Dummy (embora eu não tenha inventado isso, então não me credite).

Resumindo: basta inserir isso no seu <form>e verificar se ele está vazio ao validar:

<input type="text" name="email" style="display:none" />

O truque é enganar um bot para pensar que ele precisa inserir dados em um campo obrigatório, por isso nomeei a entrada "email". Se você já possui um campo chamado email que está usando, tente nomear o campo fictício de outra forma como "empresa", "telefone" ou "endereço de email". Basta escolher algo que você sabe que não precisa e o que parece ser algo que as pessoas normalmente acham lógico preencher em um formulário da web. Agora esconder o inputcampo usando CSS ou JavaScript / jQuery - o que você se encaixa melhor - basta não definir a entrada typepara hiddenou então o bot não vai cair para ele.

Ao validar o formulário (no lado do cliente ou do servidor), verifique se o seu campo fictício foi preenchido para determinar se foi enviado por um humano ou um bot.

Exemplo:

No caso de um ser humano: O usuário não verá o campo fictício (no meu caso chamado "email") e não tentará preenchê-lo. Portanto, o valor do campo fictício ainda deve estar vazio quando o formulário for enviado.

No caso de um bot: o bot verá um campo cujo tipo é texte um nome email(ou como você o chama) e tentará logicamente preenchê-lo com os dados apropriados. Não importa se você estilizou o formulário de entrada com algum CSS sofisticado, os desenvolvedores da Web o fazem o tempo todo. Qualquer que seja o valor no campo fictício, não nos importamos, desde que seja maior que os 0caracteres.

Eu usei esse método em um livro de visitas em combinação com CAPTCHA e não vejo uma única postagem de spam desde então. Eu já havia usado uma solução somente CAPTCHA, mas, eventualmente, resultou em cerca de cinco postagens de spam a cada hora. A adição do campo fictício no formulário interrompeu (pelo menos até agora) todo o spam de aparecer.

Eu acredito que isso também pode ser usado muito bem com um formulário de login / autenticação.

Aviso : é claro que este método não é 100% infalível. Os bots podem ser programados para ignorar os campos de entrada com o estilo display:noneaplicado a ele. Você também precisa pensar em pessoas que usam algum tipo de preenchimento automático (como a maioria dos navegadores incorporados!) Para preencher automaticamente todos os campos do formulário. Eles podem muito bem pegar um campo fictício.

Você também pode variar um pouco deixando o campo fictício visível, mas fora dos limites da tela, mas isso depende totalmente de você.

Seja criativo!

Pieter888
fonte
33
Esse é um truque anti-spam útil, mas eu sugiro usar um nome de campo diferente de 'email' ou você pode achar que o preenchimento automático do navegador o preenche, bloqueando inadvertidamente usuários genuínos do seu site.
Nico Burns
8
Eu também tenho muitos mais destes usando visibility:hiddene também position:absolute;top:-9000pxvocê também pode fazer text-indente também z-indexem alguns desses elementos e colocá-los em nomes de arquivos CSS compactados com nomes desajeitados - desde bots podem detectar 1Exiba: none` e eles agora verificar se há uma gama de combinações - eu realmente uso esses métodos e eles são velhos truques do comércio. 1
TheBlackBenzKid
18
O que acontece quando um usuário com deficiência visual está usando um leitor de tela para navegar no formulário?
soycharliente
8
Essa técnica tem um nome: o honeypot pt.wikipedia.org/wiki/Honeypot_(computing)
pixeline
27
Não há necessidade de estilo embutido. Basta adicionar uma classe ao campo (talvez use uma palavra estranha que nunca possa significar nada para um bot) e oculte-a no arquivo CSS do site. Como: <input type="text" name="email" class="cucaracha">e no seu CSS: .cucaracha { display:none; }.
Ricardo Zea
81

Não acho que a resposta acima esteja "errada", mas há grandes áreas de autenticação que não são abordadas (ou melhor, a ênfase está em "como implementar sessões de cookie", não em "quais opções estão disponíveis e quais são as trocas comerciais" -offs ".

As minhas edições / respostas sugeridas são

  • O problema está mais na configuração da conta do que na verificação de senha.
  • O uso da autenticação de dois fatores é muito mais seguro do que meios mais inteligentes de criptografia de senha
  • NÃO tente implementar seu próprio formulário de login ou armazenamento de senhas no banco de dados, a menos que os dados armazenados não tenham valor na criação da conta e sejam gerados automaticamente (ou seja, no estilo da Web 2.0, como Facebook, Flickr , etc.)

    1. A autenticação Digest é uma abordagem baseada em padrões, suportada em todos os principais navegadores e servidores, que não envia uma senha nem mesmo por um canal seguro.

Isso evita a necessidade de ter "sessões" ou cookies, pois o próprio navegador irá criptografar novamente a comunicação. É a abordagem de desenvolvimento mais "leve".

No entanto, eu não recomendo isso, exceto para serviços públicos de baixo valor. Esse é um problema com algumas das outras respostas acima - não tente reimplementar mecanismos de autenticação no servidor - esse problema foi resolvido e é suportado pela maioria dos principais navegadores. Não use cookies. Não armazene nada em seu próprio banco de dados enrolado à mão. Basta perguntar, por solicitação, se a solicitação está autenticada. Todo o resto deve ser suportado por configuração e software confiável de terceiros.

Assim ...

Primeiro, estamos confundindo a criação inicial de uma conta (com uma senha) com a verificação posterior da senha posteriormente. Se eu sou o Flickr e estou criando seu site pela primeira vez, o novo usuário tem acesso a valor zero (espaço em branco na web). Eu realmente não me importo se a pessoa que está criando a conta está mentindo sobre seu nome. Se eu estou criando uma conta do hospital intranet / extranet, o valor encontra-se em todos os registros médicos, e assim eu faço cuidado sobre a identidade (*) do criador conta.

Esta é a parte muito, muito difícil. A única solução decente é uma rede de confiança. Por exemplo, você entra no hospital como médico. Você cria uma página da Web hospedada em algum lugar com sua foto, seu número de passaporte e uma chave pública, e mistura todos eles com a chave privada. Você então visita o hospital e o administrador do sistema examina o seu passaporte, verifica se a foto corresponde a você e depois faz o hash da página da web / foto com a chave privada do hospital. A partir de agora, podemos trocar com segurança chaves e tokens. Como qualquer pessoa que confie no hospital (existe o molho secreto). O administrador do sistema também pode fornecer um dongle RSA ou outra autenticação de dois fatores.

Mas isso é muito complicado e não muito na web 2.0. No entanto, é a única maneira segura de criar novas contas que tenham acesso a informações valiosas que não são criadas automaticamente.

  1. Kerberos e SPNEGO - mecanismos de logon único com um terceiro confiável - basicamente o usuário verifica contra um terceiro confiável. (NB, isso não é de forma alguma o OAuth não confiável )

  2. SRP - tipo de autenticação de senha inteligente sem um terceiro confiável. Mas aqui estamos falando sobre "é mais seguro usar autenticação de dois fatores, mesmo que seja mais caro"

  3. Lado do cliente SSL - forneça aos clientes um certificado de chave pública (suporte nos principais navegadores - mas levanta questões sobre a segurança da máquina do cliente).

No final, é uma troca - qual é o custo de uma violação de segurança versus o custo de implementação de abordagens mais seguras. Um dia, podemos ver uma PKI adequada amplamente aceita e, portanto, não ter mais formulários e bancos de dados de autenticação rolados. Um dia...

você cad senhor - leve isso
fonte
29
Difícil dizer qual resposta que você está falando em 'Eu não acho que a resposta acima é 'errado''
Davorak
55

Ao fazer hash, não use algoritmos de hash rápidos, como MD5 (existem muitas implementações de hardware). Use algo como SHA-512. Para senhas, hashes mais lentos são melhores.

Quanto mais rápido você criar hashes, mais rápido qualquer verificador de força bruta poderá funcionar. Os hashes mais lentos retardarão, portanto, a força bruta. Um algoritmo de hash lento tornará a força bruta impraticável para senhas mais longas (8 dígitos +)

josh
fonte
5
O SHA-512 também é rápido, portanto você precisa de milhares de iterações.
Seun Osewa
5
"não use algoritmos de hash rápido ... hashes mais lentos são melhores" - Explicação? Documentação?
one.beat.consumer
17
Explicação: Quanto mais rápido você criar hashes, mais rápido qualquer verificador de força bruta poderá funcionar. Os hashes mais lentos retardarão, portanto, a força bruta. Um algoritmo de hash lento vai fazer força bruta impraticável para senhas mais longas (8 dígitos +)
NickG
6
Mais como algo como bcrypt, que é projetado para hash lentamente.
Fabian Nicollier
4
Como mencionado em outra resposta, "OWASP recomenda o uso do Argon2 como sua primeira escolha para novos aplicativos. Se isso não estiver disponível, PBKDF2 ou scrypt deve ser usado. E, finalmente, se nenhuma das opções acima estiver disponível, use bcrypt". Nem o MD5 nem nenhuma das funções de hash do SHA devem ser usadas para senhas de hash. Esta resposta é um mau conselho.
Mike
25

Gostaria de adicionar uma sugestão que usei, com base na defesa em profundidade. Você não precisa ter o mesmo sistema de autenticação e autenticação para administradores como usuários comuns. Você pode ter um formulário de login separado em um URL separado executando código separado para solicitações que concederão altos privilégios. Este pode fazer escolhas que seriam uma dor total para usuários regulares. Uma delas que usei é realmente embaralhar o URL de login para acesso de administrador e enviar por e-mail o novo URL ao administrador. Interrompe qualquer ataque de força bruta imediatamente, pois seu novo URL pode ser arbitrariamente difícil (sequência aleatória muito longa), mas o único inconveniente do usuário administrador é seguir um link no email. O invasor não sabe mais para onde POSTAR.

Iain Duncan
fonte
Um link simples em um email não é realmente seguro, pois o email não é seguro.
David Spector
É tão seguro quanto qualquer outro sistema de redefinição de senha baseado em token que não é de dois fatores. O que é quase todos eles.
Iain Duncan
17

Não sei se era melhor responder a isso como resposta ou como comentário. Eu optei pela primeira opção.

Com relação ao argumento PARTE IV: Funcionalidade de senha esquecida na primeira resposta, gostaria de fazer um argumento sobre ataques de sincronização.

Nos formulários Lembrar sua senha , um invasor pode verificar uma lista completa de emails e detectar quais estão registrados no sistema (veja o link abaixo).

Em relação ao Formulário de senha esquecida, gostaria de acrescentar que é uma boa idéia igualar os tempos entre consultas bem-sucedidas e malsucedidas com alguma função de atraso.

https://crypto.stanford.edu/~dabo/papers/webtiming.pdf

user9869932
fonte
14

Eu gostaria de acrescentar um comentário muito importante: -

  • "Em um ambiente corporativo intra- rede", a maioria, se não todas, as opções anteriores podem não se aplicar!

Muitas empresas implantam sites de "somente uso interno" que são, efetivamente, "aplicativos corporativos" que foram implementados por meio de URLs. Esses URLs (supostamente ...) só podem ser resolvidos na "rede interna da empresa". (Que rede inclui magicamente todos os "guerreiros da estrada" conectados à VPN)

Quando um usuário está devidamente conectado à rede acima mencionada, sua identidade ("autenticação") [...] já é "conclusivamente conhecida", assim como sua permissão ("autorização") para fazer certas coisas ... como. .. "para acessar este site."

Este serviço "autenticação + autorização" pode ser fornecido por várias tecnologias diferentes, como LDAP (Microsoft OpenDirectory) ou Kerberos.

Do seu ponto de vista, você simplesmente sabe disso: que qualquer pessoa que encerre legitimamente seu site deve ser acompanhada por [uma variável de ambiente que magicamente contenha ...] um "token". ( ou seja, a ausência de um token deve ser motivo imediato para isso 404 Not Found.)

O valor do token não faz sentido para você, mas, se necessário, "existem meios adequados" pelos quais seu site pode "[autoritariamente] perguntar a alguém que conhece (LDAP ... etc.)" sobre todo e qualquer (!) pergunta que você possa ter. Em outras palavras, você não se beneficia de nenhuma "lógica doméstica". Em vez disso, você consulta a Autoridade e confia implicitamente em seu veredicto.

Uh huh ... é bastante um mentais-chave do "Internet wild-e-lanoso."

Mike Robinson
fonte
9
Você caiu na pontuação bem quando criança? :) Eu li três vezes e ainda estou perdido em que ponto você está tentando fazer. Mas se você está dizendo "Às vezes você não precisa de autenticação baseada em formulário", está certo. Mas considerando que estamos discutindo quando precisamos, não vejo por que isso é muito importante notar.
Hugo Delsing
1
Meu argumento é que o mundo fora de uma corporação é totalmente diferente do mundo dentro. Se você estiver criando um aplicativo que seja acessível à "rede lanosa" e para consumo geral do público, não terá outra opção a não ser rolar seus próprios métodos de autenticação e autorização. Mas, dentro de uma corporação, onde a única maneira de chegar lá é estar lá ou usar VPN, é muito provável que o aplicativo não tenha - não tenha - métodos próprios para fazer essas coisas. O aplicativo deve usar esses métodos, para fornecer um gerenciamento centralizado e consistente.
Mike Robinson
2
Até as intranets exigem uma quantidade mínima de segurança no edifício. As vendas têm números confidenciais de lucros e perdas, enquanto a engenharia possui propriedade intelectual confidencial. Muitas empresas restringem os dados por linhas departamentais ou divisórias.
Sablefoste 30/07