Percebi que a maioria dos sites envia as senhas como texto simples por HTTPS para o servidor. Existe alguma vantagem se em vez disso eu enviar o hash da senha para o servidor? Seria mais seguro?
Percebi que a maioria dos sites envia as senhas como texto simples por HTTPS para o servidor. Existe alguma vantagem se em vez disso eu enviar o hash da senha para o servidor? Seria mais seguro?
Respostas:
Esta é uma questão antiga, mas senti necessidade de dar a minha opinião sobre este importante assunto. Há muita desinformação aqui
O OP nunca mencionou o envio da senha clara por HTTP - apenas HTTPS, mas muitos parecem estar respondendo à questão de enviar uma senha por HTTP por algum motivo. Dito isto:
Acredito que as senhas nunca devem ser retidas (muito menos transmitidas) em texto simples. Isso significa que não é guardado no disco, nem mesmo na memória.
As pessoas que responderam aqui parecem pensar que HTTPS é uma bala de prata, o que não é. No entanto, isso certamente ajuda muito e deve ser usado em qualquer sessão autenticada.
Não há realmente necessidade de saber o que é uma senha original. Tudo o que é necessário é uma maneira confiável de gerar (e gerar novamente de forma confiável) uma "chave" de autenticação com base no texto original escolhido pelo usuário. Em um mundo ideal, esse texto deve gerar imediatamente uma "chave", fazendo o hash usando sal irreversível. Este sal deve ser exclusivo para a credencial do usuário que está sendo gerada. Essa "chave" será o que seus sistemas usarão como senha. Dessa forma, se seus sistemas forem comprometidos no futuro, essas credenciais só serão úteis contra sua própria organização e em nenhum outro lugar onde o usuário foi preguiçoso e usou a mesma senha.
Portanto, temos uma chave. Agora precisamos limpar qualquer vestígio da senha no dispositivo do cliente.
Em seguida, precisamos obter essa chave para seus sistemas. Você nunca deve transmitir uma chave ou senha "às claras". Nem mesmo por HTTPS. HTTPS não é impenetrável. Na verdade, muitas organizações podem se tornar um MITM confiável - não da perspectiva de um ataque, mas para realizar inspeções no tráfego para implementar suas próprias políticas de segurança. Isso enfraquece o HTTPS, e não é a única maneira que acontece (como redirecionamentos para ataques HTTP MITM, por exemplo). Nunca assuma que é seguro.
Para contornar isso, hash a chave com um nonce único. Este nonce é exclusivo para cada envio de uma chave para seus sistemas - até mesmo para a mesma credencial durante a mesma sessão, se você precisar enviá-la várias vezes. Você pode reverter esse nonce assim que chegar em seus próprios sistemas para recuperar a chave de autenticação e autenticar a solicitação.
Nesse ponto, eu faria um hash irreversível dele uma última vez antes que ele seja armazenado permanentemente em seus próprios sistemas. Dessa forma, você pode compartilhar o sal da credencial com organizações parceiras para fins de SSO e semelhantes, ao mesmo tempo que pode provar que sua própria organização não pode se passar pelo usuário. A melhor parte dessa abordagem é que você nunca compartilha nada gerado pelo usuário sem sua autorização.
Faça mais pesquisas, pois há mais do que eu mesmo divulguei, mas se você quiser fornecer segurança real aos seus usuários, acho que este método é atualmente a resposta mais completa aqui.
TL; DR:
Use HTTPS. Faça hash de senhas de forma segura, irreversivelmente, com um sal exclusivo por senha. Faça isso no cliente - não transmita sua senha real. Transmitir a senha original dos usuários para seus servidores nunca é "OK" ou "Tudo bem". Limpe qualquer vestígio da senha original. Use um nonce independentemente de HTTP / HTTPS. É muito mais seguro em vários níveis. (Resposta ao OP).
Como é HTTPS, definitivamente não há problema em enviar a senha sem hashing (HTTPS não é texto simples). Além disso, se o seu aplicativo depende de HTTPS para manter seu conteúdo seguro, então é inútil hash a senha antes de enviá-la por HTTPS (ou seja, se um invasor puder descriptografar os dados durante a transmissão, você está ferrado de qualquer maneira)
Não, na verdade, isso seria uma vulnerabilidade. Se o invasor conseguir obter o hash do banco de dados, ele poderá usá-lo para autenticar sem precisar quebrá-lo. Sob nenhuma circunstância um usuário ou invasor pode obter uma senha de hashes.
O objetivo de fazer hash de senhas é adicionar uma camada extra de segurança. Se um invasor for capaz de obter o hash e o salt do banco de dados usando SQL Injection ou um backup inseguro, ele terá que encontrar o texto simples por força bruta. John The Ripper é comumente usado para quebrar hashes de senha com sal.
Não usar https é uma violação do OWASP Top 10: A9-Insufficient Transport Layer Protection
EDIT:
Se em sua implementação você calcular um sha256(client_salt+plain_text_password)
e depois calcular outro hash no lado do servidorsha256(server_salt+client_hash)
então esta não é uma vulnerabilidade séria. No entanto, ele ainda é suscetível a espionagem e repetição da solicitação. Portanto, esta ainda é uma violação clara do WASP A9. No entanto, isso ainda está utilizando um resumo da mensagem como uma camada de segurança.
A coisa mais próxima que vi de uma substituição do lado do cliente para https é um diffie-hellman na troca de chaves em javascript . No entanto, isso impede ataques MITM ativos e, portanto, é até tecnicamente uma violação do OWASP A9. Os autores do código concordam que esta não é uma substituição completa para HTTPS, no entanto, é melhor do que nada e melhor do que um sistema de hash do lado do cliente.
Enviar um hash pela rede anula completamente o propósito do hash, porque um invasor pode simplesmente enviar o hash e esquecer a senha. Em suma, um sistema que atentica usando um hash em texto não criptografado é totalmente aberto e pode ser comprometido com nada mais do que uma detecção de rede.
A senha em texto simples mostra nunca (nem mesmo quando usando HTTPS) deixa o cliente. Deve ser feito um hash irreversível antes de deixar o cliente, pois não é necessário que o servidor saiba a senha real.
O hash e a transmissão resolvem problemas de segurança para usuários preguiçosos que usam a mesma senha em vários locais (eu sei que sim). No entanto, isso não protege seu aplicativo como um hacker que obteve acesso ao banco de dados (ou de qualquer outra forma conseguiu colocar as mãos no hash), pois o hacker poderia simplesmente transmitir o hash e fazer com que o servidor o aceitasse.
Para resolver esse problema, você pode, obviamente, apenas fazer o hash do hash que o servidor recebe e encerrar o dia.
Minha abordagem para o problema em um aplicativo da web baseado em soquete que estou criando é que, na conexão com o cliente, o servidor gera um salt (string aleatória a ser adicionada antes do hash) e o armazena na variável sockets, em seguida, ele transmite esse hash para o cliente. O cliente pega a senha do usuário, faz o hash, adiciona o salt do servidor e faz o hash de tudo, antes de transmiti-lo ao servidor. Em seguida, é enviado para o servidor que compara esse hash com o hash (hash no DB + salt). Pelo que eu sei, essa é uma boa abordagem, mas para ser justo, não li muito sobre o assunto e se estiver errado sobre alguma coisa, adoraria ser corrigido :)
Use HTTP Digest - ele protege a senha até mesmo em http (mas o melhor uso seria http digest em https)
Wikipedia:
A autenticação de acesso HTTP digest é um dos métodos acordados que um servidor da web pode usar para negociar credenciais com um usuário da web (usando o protocolo HTTP). A autenticação Digest tem como objetivo substituir o uso não criptografado da autenticação de acesso Básico, permitindo que a identidade do usuário seja estabelecida com segurança sem a necessidade de enviar uma senha em texto simples pela rede. A autenticação Digest é basicamente uma aplicação de hashing criptográfico MD5 com o uso de valores nonce para evitar a criptoanálise.
Link: http://en.wikipedia.org/wiki/Digest_access_authentication
Se você quiser ver um uso na "vida real", você pode olhar para phpMyID - um provedor de openid de php que usa autenticação http digest http://siege.org/phpmyid.php
.. ou você pode começar a partir dos exemplos de autenticação php em http://php.net/manual/en/features.http-auth.php
Rfc de resumo HTTP: http://www.faqs.org/rfcs/rfc2617
De meus testes, todos os navegadores modernos o suportam ...
Se você deseja substituir uma senha de texto simples sobre HTTPS por uma senha com hash sobre HTTP, então você está procurando problemas. HTTPS gera uma chave de transação compartilhada aleatória ao abrir um canal de comunicação. Isso é difícil de decifrar, já que você está praticamente limitado à força bruta da chave compartilhada usada para uma transação (relativamente) de curto prazo. Considerando que seu hash pode ser apenas cheirado, retirado da linha e pesquisado em uma tabela de arco-íris ou apenas forçado de forma bruta por um longo período de tempo.
No entanto, uma ofuscação de senha básica do lado do cliente (não hash) enviada por HTTPS tem algum valor. Se não me engano, esta técnica é usada por alguns bancos. O objetivo desta técnica não é proteger a senha contra o rastreamento através do fio. Em vez disso, é para impedir que a senha seja utilizável para ferramentas de espionagem idiotas e plug-ins de navegador que simplesmente capturam todas as solicitações HTTPS GET / POST que veem. Eu vi um arquivo de log capturado de um site malicioso com 400 MB de transações GET / POST aleatórias capturadas de sessões de usuário. Você pode imaginar que sites que usaram apenas HTTPS apareceriam com senhas de texto não criptografado no log, mas sites com ofuscação muito básica (ROT13) também apareceriam com senhas que não são imediatamente úteis.
Se você estiver conectado a um servidor https, o fluxo de dados entre o servidor e o navegador deve ser criptografado. Os dados são apenas texto simples antes de serem enviados e depois de recebidos. Artigo da Wikipedia
Aviso: Não sou um especialista em segurança - e estou postando com a esperança que outros critiquem minha posição como excessivamente cautelosa ou improvável e que eu aprenda com isso. Dito isso, só quero enfatizar que o hash quando sai do seu cliente não significa que você não precisa fazer o hash no back-end antes de colocá-lo no banco de dados.
Faz ambos
Faça ambos porque:
O hash durante a viagem ajuda a cobrir vulnerabilidades de transporte. Se a conexão SSL for comprometida, eles ainda não poderão ver a senha bruta. Não importa em termos de ser capaz de se passar por usuários autorizados, mas irá proteger seus usuários de terem suas senhas lidas em associação com seus e-mails. A maioria das pessoas não segue as práticas recomendadas e usa a mesma senha para muitas de suas contas, então isso pode ser uma vulnerabilidade séria para seus visitantes.
Se alguém, de alguma forma, conseguiu ler as senhas do banco de dados (isso acontece, pense na injeção de SQL), ainda não será capaz de executar ações privilegiadas se passando por usuários por meio da minha API. Isso ocorre por causa da assimetria do hash; mesmo se eles souberem o hash armazenado em seu banco de dados, eles não saberão a chave original usada para criá-lo e é isso que o middleware de autenticação usa para autenticar. É também por isso que você deve sempre salgar seu armazenamento de hash.
É verdade que eles poderiam causar muitos outros danos se tivessem as rédeas soltas para ler o que desejam de seu banco de dados.
Eu só quero enfatizar aqui que se você decidir fazer o hash da chave antes de sair de seus clientes, isso não é suficiente - o hashing de back-end é, imo, muito mais importante e este é o motivo: Se alguém está interceptando o tráfego de seu cliente, eles verão o conteúdo do password
campo. Quer seja um hash ou texto simples, não importa - eles podem copiá-lo literalmente para se passar por um cliente autorizado. (A menos que você siga as etapas descritas em @ user3299591, e eu recomendo que você faça). O hash da coluna DB, por outro lado, é uma necessidade e nada difícil de implementar.
O SSL / TLS não está substituindo o nonce? Não vejo valor agregado nisso, já que SSL / TLS também protege contra ataques de repetição.
Na verdade, seria menos seguro fazer o hash da senha e enviá-la por um canal não criptografado. Você exporá seu algoritmo de hashing no cliente. Os hackers podem simplesmente farejar o hash da senha e usá-lo para invadir mais tarde.
Ao usar HTTPS, você evita que um hacker obtenha a senha de uma única fonte, já que o HTTPS usa dois canais, ambos criptografados.
Se há uma vantagem e se é mais (ou menos) seguro realmente depende da implementação. Pode-se dizer que há alguma vantagem, mas se você implementá-la mal, pode definitivamente criar uma solução que seja menos segura do que passar até mesmo uma senha de texto simples.
Isso pode ser visto da perspectiva de dois tipos de ataques - um com acesso ao tráfego da rede e outro com acesso ao banco de dados.
Se o seu invasor puder interceptar a versão em texto simples do tráfego de rede, ver um hash da senha é mais seguro do que ver a senha em texto simples. Embora o invasor ainda possa se conectar ao seu servidor usando esse hash, seria necessário um crack de força bruta (às vezes pré-calculado) desse hash para determinar a senha que pode ser útil em outros sistemas. As pessoas devem usar senhas diferentes em sistemas diferentes, mas geralmente não o fazem.
Se um invasor obtiver acesso ao banco de dados, talvez por meio de uma cópia de um backup, você deve garantir que ninguém possa efetuar login apenas com esse conhecimento. Se, por exemplo, você armazenou um hash salgado com o nome de login comohash(login_name+password)
e passou esse mesmo hash do cliente para comparação direta, o invasor poderia escolher um usuário aleatoriamente, enviar o hash lido do banco de dados e fazer login como aquele usuário sem saber a senha, aumentando o escopo da violação. Nesse caso, enviar a senha em texto simples teria sido mais seguro porque o invasor precisaria conhecer o texto simples para fazer o login, mesmo tendo uma cópia do banco de dados. É aqui que a implementação é fundamental. Se você enviar uma senha de texto simples ou um hash do lado do cliente dessa senha, você deve fazer o hash desse valor no lado do servidor e comparar esse hash com o hash armazenado no registro do usuário.
Conceitos a ter em mente: