Devo criptografar a senha antes de enviá-la para o servidor?


110

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?


5
@Jader Dias: Eu sei que você não perguntou isso, mas não ficaria mais seguro se você hash, ENTÃO envie por https. Na verdade, pode torná-lo menos seguro, já que você expõe seu sal. Além disso, (falando do meu lado posterior aqui), a mistura de algoritmos pode causar mais colisões de hash e torná-lo mais hackeavel.
Merlyn Morgan-Graham

@Merlyn "colisões de hash" bom ponto!
Jader Dias

A mistura de algoritmos não aumenta a probabilidade de colisão de forma alguma. Esse é o ponto principal de uma função hash. Dada qualquer entropia de entrada, retorna a saída que tem uma probabilidade igual de estar em qualquer lugar no espaço de saída possível.
JJ

@JJ "A mistura de algoritmos não aumenta a probabilidade de colisão de forma alguma." Eu realmente gostaria de ver uma prova dessa afirmação. Deixe-me interromper: isso é falso , em geral aumenta as colisões. Posso construir facilmente uma função de hash de modo que h (x) não seja constante 0, mas h (h (x)) = 0 para todo x. Portanto, você teria que se referir ao conjunto exato de algoritmos de hash e como você os mistura. Então você precisaria provar sua declaração. AFAIK, mesmo para vários SHA (com sal), este é um problema aberto. E basicamente acreditamos que isso seja verdade. A criptografia é difícil.
bizarro

Respostas:


155

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).


25
Acabei de verificar as ferramentas de desenvolvedor do gmail e do Facebook - Chrome que me dizem POST e uma mensagem codificada por url contendo meu nome de usuário e senha em texto simples (sem sal). Como / por que os grandes jogadores não estão usando sal não comercial no cliente?
Gremwell

18
Você hash a chave com um nonce e afirma ser capaz de reverter o nonce no lado do servidor. Você está fazendo força bruta no hash, então? Ou como você recupera um nonce ao obter um hash = HASH (secret + nonce) HASH deve ser uma função irreversível. Você implementou isso? Não acho que o que você explica seja viável. Você pode criar um fluxograma do protocolo?
Prata

19
Se você não confia no HTTPS, todo esforço é inútil! Seu código é enviado através do fio e um invasor pode modificar / substituir todas as suas tentativas de proteger a senha em trânsito
Sajid Kalla

3
Um MitM que pode reescrever um certificado pode reescrever o nonce. Ou o que Sajid disse.
leewz

4
Se você está preocupado com MITM com HTTPS, de que adianta enviar um salt ao cliente para que o cliente possa salgar a senha antes de transmitir o hash de volta ao servidor? Parece inútil. É melhor fazer um hash sem sal no servidor e, em seguida, usar um salt para fazer o hash novamente no servidor. Obviamente, o cliente também não pode ser o gerador do sal do cliente porque no próximo login seria diferente e não computaria o mesmo hash do lado do servidor.
esmagamento de

24

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)


5
Isso não deve ser um problema. Se o cliente estiver usando um proxy, tudo o que o proxy verá são os dados criptografados HTTPS. Se você estiver falando sobre um ataque man-in-the-middle, um certificado configurado corretamente deve evitar isso.
Kiersten Arnold

7
@Jader: Não mexer nos dados vai impedir um ataque MITM, já que ele pode simplesmente transmitir o que quer que aconteça. Não importa se você está transmitindo uma senha ou hash. É uma questão completamente diferente.
David Thornley

2
O objetivo do SSL (HTTPS = HTTP sobre SSL) é impedir o MITM.
yfeldblum

1
@carnold - MINTM - Que tal redirecionar para http? A maioria das pessoas notaria? sslstrip - securityfocus.com/brief/910
nate c

1
@Jader Dias você está tentando acabar com um problema que não existe. HTTPS interrompe esse problema, um hash do lado do cliente não adiciona qualquer quantidade de segurança. O cliente nunca é confiável.
torre

17

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.


4
Na verdade, eu faria o hash novamente no servidor, portanto, edite sua resposta contemplando este cenário.
Jader Dias

@Rook está usando a troca de chaves diffie-hellman junto com https é uma solução "inútil"? (Quero dizer, só podemos usar https e diffie helman não aumentam o imao de segurança)
Michel Gokan

@Michel Kogan uma troca de chave DH pode ser usada em HTTPs junto com outras ferramentas.
torre

1
@Rook É uma prática recomendada aplicar um hash no servidor, então acho que você deve atualizar o início de sua resposta para não descartar o hash do lado do cliente, e só então mencionar que os hashes e sais armazenados do servidor nunca devem ser expostos.
Levente Pánczél

8

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.


2
Isso parece besteira total ... Como um hash é menos seguro do que uma senha?
Levente Pánczél de

1
Isso só é verdade para hashes "burros". Considere o seguinte: um servidor envia um salt S para o cliente e o cliente faz HASH (S + PASSWORD) e o envia para o servidor. O servidor respeita esse hash específico apenas para a sessão atual. Um invasor pode realmente enviar o hash e esquecer a senha, mas SOMENTE PARA A SESSÃO ATUAL. Portanto, é mais seguro do que texto simples.
Hello World

Atualização: Digest Access Authentication é ainda mais sofisticado: en.wikipedia.org/wiki/Digest_access_authentication
Hello World

2
Só para deixar claro: quando digo "derrota o propósito do hash", estou me referindo à prática comum e segura de fazer hash de senhas antes de armazená-las em um banco de dados. No entanto, o argumento sustenta que enviar um valor hash em vez de uma senha não faz nada para aumentar a segurança sem etapas adicionais.
Paul Keister

Só para acrescentar ao que Paulo disse: esse tipo de ataque é chamado de “ataque de repetição” se alguém quiser ler mais sobre isso em outro lugar.

5

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 :)


3

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 ...


O HTTP Digest implementa o que quero dizer nesta pergunta, mas teríamos alguma vantagem se usássemos HTTPS Digest (SSL + HTTP Digest)?
Jader Dias

Uma diferença principal seria que tudo é enviado / recebido criptografado - cabeçalhos http enviados e recebidos e a resposta html. Para alguém que está tentando "hackear" o SSL aleatoriamente usando um ataque man-in-the-middle, o resumo http seria um motivo extra para fazê-lo pesquisar outro alvo mais fácil, ou se ele estiver registrando todo o tráfego capturado, suas senhas ainda são mais seguras. Posso ter entendido mal a pergunta, inglês não é minha primeira língua.
vlad b.

O hash sobre a senha tem uma grande vantagem: se o tráfego for registrado ou capturado de alguma forma, isso tornará o trabalho mais difícil para aquela pessoa. Além disso, com o resumo de http, se o SSL nem sempre for necessário, você pode permitir que os usuários escolham entre http e https. Ou você pode usar protocolos diferentes para servidores diferentes (por exemplo, eu não imponho https para visualizar / modificar menos dados importand (nome de usuário, upload de avatar), mas imponho https na cobrança e em outras partes do site (dessa forma, posso diminuir a carga em alguns servidores, se / quando necessário).
vlad b.

3

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.


"mas sites com ofuscação muito básica (ROT13) também apareceriam com senhas que não são imediatamente úteis" - isso contradiz a declaração original. A chave é que eles não são IMEDIATAMENTE úteis, mas isso é realmente fútil. A senha e seu ROT13 são equivalentes. MAS se você SHA2 a senha, ela não estará presente nos logs (para que seus administradores não conheçam as possíveis senhas dos usuários para outros sistemas), e você JÁ NÃO está violando quase todas as leis de privacidade.
Levente Pánczél

2

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


Os proxies não interceptam esses dados?
Jader Dias

Pelo que entendi, eles fazem, mas o proxy não é responsável pela criptografia / descriptografia e, a menos que seja um proxy sem escrúpulos, apenas passa os dados adiante. O tipo e a força da criptografia dependem do que o servidor e o cliente podem suportar.
jac

1
Mesmo que o proxy seja ininterrupto, ele não pode descriptografar os dados, pois eles são criptografados usando a chave pública do servidor. A única maneira de um proxy descriptografar os dados é falsificar o certificado do servidor com uma chave diferente
Kiersten Arnold

@Jader. Se o fizessem, tornaria o HTTPS muito ruim. quando você se autentica em um servidor com HTTPS, está obtendo uma garantia (assumindo que o certificado é válido) de que está se conectando a um determinado servidor e possui um caminho criptografado de uma extremidade à outra. Hipoteticamente, um ataque intermediário poderia ser feito para enganá-lo, é claro, mas isso não é o mesmo que um proxy da web básico.
Peter Recore

2

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:

  1. 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.

  2. 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 passwordcampo. 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.



0

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.


1
Na verdade, eu faria o hash novamente no servidor e usaria HTTPS de qualquer maneira, então edite sua resposta contemplando este cenário.
Jader Dias

@Jader, a questão é que tudo o que um invasor precisa agora é o primeiro hash, em vez de uma senha. Na verdade, o hash que você obtém da senha no lado do cliente agora é tão útil quanto a própria senha. Então, você não está realmente ganhando muita segurança.
Peter Recore

Alguém já pensou em não enviar partes do token? Por exemplo, se você conhece seus métodos de hash, por que enviaria isso. o servidor não deve saber a chave do cliente para descriptografar?
jemiloii

0

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:

  • Você "salga" um hash misturando algum valor exclusivo de escopo ao seu hash, normalmente exclusivo de linha. Seu objetivo é garantir a exclusividade dos hashes, mesmo que os valores de texto simples que eles representam sejam os mesmos, para que dois usuários com a mesma senha ainda tenham hashes diferentes. Não é necessário tratar o sal como segredo.
  • Ao autenticar, sempre hash no lado do servidor qualquer valor que você passar do cliente como uma senha (mesmo se já tiver hash) e compare-o com um valor pré-hash armazenado no banco de dados. Isso pode exigir o armazenamento de uma versão com hash duplo da senha original.
  • Ao fazer um hash, considere adicionar um salt exclusivo de servidor / cluster ao hash, bem como um salt exclusivo de linha para proteger contra a correspondência de quaisquer hashes pré-calculados nas tabelas de pesquisa.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.