Eu queria saber se as entradas das senhas são "convertidas" localmente no lado do cliente/navegador da Web ou no lado do servidor.
Tenho quase certeza que é do lado do servidor, mas nesse caso me traz uma preocupação: isso significa que você está enviando sua senha para um terceiro. Na verdade, a senha viajará em um canal seguro para o servidor, mas no final o servidor poderá fazer o que quiser com ela. Calcular você mesmo o hash e enviá-lo ao servidor tornaria o processo de autenticação muito mais seguro.
Caso o cenário local não seja possível, você poderia explicar como tenho 5 anos por que isso não é possível ou é uma boa ideia?
Normalmente (com logins baseados em formulários regulares) tudo é feito no lado do servidor.
Sim, poderia. Daí as advertências contra a reutilização de senha.
Por conta própria – não, não vai. Ele vai trocar um risco por outro.
Com o hash do lado do servidor, se o banco de dados do servidor vazar (o que acontece com muito mais frequência do que o TLS MITM), esses hashes são inúteis, a menos que sejam quebrados um por um. Com o hash do lado do cliente, o invasor pode simplesmente começar a enviar esses hashes como se fossem senhas! Em vez de um vazamento de banco de dados único, agora o invasor pode fazer login nas contas de todos e pode manter esses hashes para si e usá-los para fazer login meses ou anos depois.
(Se você fez ambos os lados (primeiro cliente, depois servidor) hash as senhas, isso ainda não impediria um servidor malicioso de armazenar os hashes enviados pelo cliente e reenviá-los para outro lugar, novamente como senhas.)
Para evitar os dois problemas, você precisaria de mais do que apenas hash; você precisaria de um protocolo um pouco mais complexo (por exemplo, algum tipo de desafio/resposta que não seja completamente mal projetado como "HTTP Digest" foi). Você também deseja garantir que o hash enviado pelo cliente não possa ser reutilizado posteriormente (ou mesmo em um site diferente), pois "ataques de repetição" são um problema com muitos protocolos.
Por exemplo, o protocolo SCRAM agora é um pouco comum entre sistemas não web, como PostgreSQL ou MongoDB. No entanto, para um desenvolvedor da Web, tudo isso é significativamente mais complexo do que apenas criar um HTML
<form>
– eles exigem código JavaScript personalizado e geralmente exigem interação em várias etapas com o servidor.Parece que "já que estamos adicionando JavaScript de qualquer maneira", a web em geral está se movendo para protocolos que não envolvem senhas , como WebAuthn, que funciona com assinaturas de chave pública (um pouco como SSH). Isso não significa necessariamente dongles de hardware e 2FA – "Windows Hello PIN" é um exemplo de WebAuthn fornecido pelo sistema operacional.
Não, aceitar hashes em vez de senhas tornaria o processo muito menos seguro . Seria o mesmo que manter senhas em texto simples: se um invasor roubar o banco de dados do servidor contendo nomes de usuário e hashes, ele poderá fazer login instantaneamente como qualquer usuário!
Todo o propósito do hash é forçar os invasores a reverter uma função unidirecional: calcular um hash de uma senha conhecida é trivial, encontrar senhas que correspondam a um determinado hash é difícil. Senhas ruins, como palavras de dicionário, são comprometidas quando os hashes são roubados, porque a computação de hashes com mais de 100.000 palavras é rápida. Boas senhas permanecem seguras, porque para calcular o hash você precisa adivinhar a senha primeiro.
Sim, quando você digita uma senha em um site, ela é transmitida ao servidor em texto simples, e o script no servidor pode fazer qualquer coisa com ela, até mesmo armazená-la em texto simples. Para proteger os usuários (os sites são exigidos por lei na maioria dos países), eles fazem o hash da senha e armazenam apenas o hash, mas isso não significa que isso sempre aconteça.
Mas mesmo assim, se um hash de senha for hackeado, ele poderá eventualmente ser revertido para uma senha simples, se realmente desejado e houver tempo suficiente disponível (dado que eles também obtêm o hash de segurança).
Então, o que isso significa, sempre use senhas exclusivas em cada site. É melhor usar um gerenciador de senhas que vem com um gerador de senhas aleatório para que você possa lembrar apenas uma senha e esquecer o resto. Existem soluções baseadas em nuvem, mas também soluções locais, dependendo do quanto você desconfia da computação em nuvem.
Quanto à computação do hash localmente, tecnicamente é possível fazer isso com javascript, mas traz um enorme risco de segurança. Ao criar um hash de senha, você usa um hash exclusivo (hash de segurança) no qual o hash eventualmente se baseia. Como esse hash exclusivo não é conhecido localmente, não é possível descriptografar a senha. Se você fizer hash local, de repente o servidor deve primeiro enviar o hash de segurança secreto para obter a senha com hash. Um hacker poderia descriptografar facilmente qualquer hash.
A senha deve ser hash no lado do servidor. Se você fizer o hash da senha no cliente no lado do servidor e enviar a senha com hash para o servidor, a senha com hash será o que o servidor verifica para autenticá-lo, e "coisa que o servidor verifica para autenticá-lo" é, por definição, a senha. Então, por definição, o que você envia ao servidor é a senha. Se o que você envia é gerado pelo hash de algo, então você está fazendo um monte de trabalho extra sem motivo. Mais importante, a substituição de sua senha pelo hash de sua senha do lado do servidor é inútil, pois não faz nada para alterar o vetor de ameaça de "se alguém invadir o servidor, eles terão dados que permitirão que eles façam login em sua conta ". A questão toda é que o servidor não tenha informações que permitam autenticação;
Ummm... sim? Não é possível criar um sistema de segurança que proteja contra o vetor de ameaças de "As pessoas que executam o servidor estão fazendo coisas que não deveriam estar fazendo".
Não, porque, como expliquei, isso significaria que você está enviando o que efetivamente é sua senha. Ou seja, você está enviando algo que, se interceptado, permitiria acesso gratuito à sua conta. Nem o envio da versão com hash nem o envio da versão sem hash abordam esse vetor de ameaça. De qualquer forma, qualquer pessoa que possa ler o tráfego pode se passar por você.
Para lidar com esse vetor, você precisaria de outros protocolos de segurança, como ter a comunicação por meio de um canal criptografado e exigir que todas as mensagens incluíssem um salt gerado aleatoriamente que muda de sessão para sessão.
Nunca confie no cliente
Com bastante tempo e dedicação, qualquer cliente pode ser modificado pelo usuário.
Vamos supor que eu seja um hacker.
Acabei de hackear o banco de dados superuser.com e agora tenho uma lista muito longa de nomes de usuário e suas senhas.
Exceto que as senhas são hash, então não posso usá-las.
Mas as senhas não são criptografadas no servidor, elas são criptografadas no meu navegador.
Portanto, tudo o que preciso fazer é modificar o script de login do JavaScript para remover o processo de hash.
E eu já conheço todos os hashes de qualquer maneira.
Como você pode ver, o hash da senha no cliente torna todo o processo de hash inútil.
Por outro lado, se o hash fosse tratado no servidor, toda a história mudaria drasticamente:
As senhas são hash no servidor, então eu realmente preciso saber a senha.
Se eu pudesse contornar o processo de hash no servidor, nem precisaria roubar as senhas em primeiro lugar; Eu poderia simplesmente forçar o servidor a me deixar entrar.
Então agora preciso gastar muito tempo e energia para encontrar uma senha cujo hash corresponda ao hash que roubei.
É por isso que o hash é sempre feito no lado do servidor, nunca no lado do cliente. E é também por isso que "Nunca confio no cliente".
TL;DR
Você deve fazer o hash da senha no lado do cliente e novamente no lado do servidor. A senha inserida na caixa de entrada de senha deve existir apenas temporariamente na memória antes do hash e deve ser excluída o mais rápido possível após a conclusão.
Hash do lado do cliente
Se um usuário reutilizar uma senha, mas ela estiver com hash no lado do cliente com um sal específico para esse site, se um invasor conseguir ler o tráfego enviado ao servidor, ele só terá acesso ao site que comprometeu o tráfego para.
Vale a pena notar que, se o invasor tiver a capacidade de gravar nos dados enviados ao cliente, ele poderá alterar o cliente para que a senha seja enviada apenas em texto simples diretamente ao invasor. O hash do lado do cliente protege apenas contra alguém que tem acesso de leitura aos dados que vão do cliente para o servidor, mas que não tem acesso de gravação aos dados que vão do servidor para o cliente.
Hash do lado do servidor
Quando o servidor faz o hash da senha antes de armazená-la/verificá-la, o usuário fica protegido contra um invasor que obtém acesso de leitura ao banco de dados. Um invasor que pode ler o banco de dados verá apenas o hash da senha, mas não conhecerá a pré-imagem desse hash, portanto não poderá se autenticar no servidor.
Vale a pena notar que, se o invasor tiver acesso de gravação ao banco de dados, puder ler a memória do aplicativo de autenticação ou executar o código do lado do servidor, essa proteção não ajudará, pois o invasor poderá interceptar as senhas antes que elas sejam criptografadas. servidor. No entanto, apenas os usuários que se autenticam enquanto o invasor tem esse acesso correm risco.
Faz ambos
Um aplicativo bem projetado que se preocupa com a segurança de seus usuários deve exercer uma estratégia de defesa em profundidade onde você faz hash tanto no cliente quanto no servidor para que o usuário fique protegido de diversos ataques. O hash do lado do servidor é mais comum do que o hash do lado do cliente, pois o acesso de leitura aos bancos de dados parece ser um comprometimento mais comum, mas isso não significa que você deva ignorar os ataques MITM que obtêm acesso de leitura ao tráfego da rede.