A necessidade de esconder o sal para um hash

99

No trabalho, temos duas teorias concorrentes para os sais. Os produtos em que trabalho usam algo como um nome de usuário ou número de telefone para adicionar o hash. Essencialmente, algo diferente para cada usuário, mas que está prontamente disponível para nós. O outro produto gera aleatoriamente um salt para cada usuário e muda cada vez que o usuário altera a senha. O salt é então criptografado no banco de dados.

Minha pergunta é se a segunda abordagem é realmente necessária? Posso entender de uma perspectiva puramente teórica que é mais seguro do que a primeira abordagem, mas e do ponto de vista prático. Agora, para autenticar um usuário, o salt deve ser descriptografado e aplicado às informações de login.

Depois de pensar sobre isso, simplesmente não vejo um ganho real de segurança com essa abordagem. Alterar o salt de conta para conta ainda torna extremamente difícil para alguém tentar forçar o algoritmo de hashing, mesmo se o invasor estiver ciente de como determinar rapidamente o que era para cada conta. Isso pressupõe que as senhas são suficientemente fortes. (Obviamente, encontrar o hash correto para um conjunto de senhas com dois dígitos é significativamente mais fácil do que encontrar o hash correto de senhas com 8 dígitos). Estou incorreto em minha lógica ou há algo que estou perdendo?

EDIT: Ok, então aqui está a razão pela qual eu acho que é realmente discutível criptografar o sal. (deixe-me saber se estou no caminho certo).

Para a explicação a seguir, assumiremos que as senhas têm sempre 8 caracteres e o salt é 5 e todas as senhas são compostas de letras minúsculas (isso apenas torna a matemática mais fácil).

Ter um sal diferente para cada entrada significa que não posso usar a mesma tabela de arco-íris (na verdade, tecnicamente, poderia se tivesse um de tamanho suficiente, mas vamos ignorar isso por enquanto). Pelo que entendi, essa é a verdadeira chave do sal, porque para quebrar todas as contas tenho que reinventar a roda, por assim dizer, para cada um. Agora, se eu souber como aplicar o salt correto a uma senha para gerar o hash, faria isso porque um salt realmente apenas estende o comprimento / complexidade da frase com hash. Portanto, estaria cortando o número de combinações possíveis que precisaria gerar para "saber" que tenho a senha + salt de 13 ^ 26 para 8 ^ 26 porque sei o que é o sal. Isso torna tudo mais fácil, mas ainda muito difícil.

Então, para criptografar o sal. Se eu souber que o salt está criptografado, não tentaria descriptografá-lo (presumindo que sei que ele tem um nível suficiente de criptografia) primeiro. Eu iria ignorar isso. Em vez de tentar descobrir como descriptografá-lo, voltando ao exemplo anterior, eu apenas geraria uma tabela de arco-íris maior contendo todas as chaves de 13 ^ 26. Não saber o sal definitivamente iria me atrasar, mas não acho que acrescentaria a tarefa monumental de tentar quebrar a criptografia do sal primeiro. É por isso que acho que não vale a pena. Pensamentos?

Aqui está um link que descreve por quanto tempo as senhas resistem a um ataque de força bruta: http://www.lockdown.co.uk/?pg=combi

kemiller2002
fonte
Boa pergunta, Kevin, muito oportuna. Não posso comentar sobre segurança, mas há uma queda de desempenho para toda essa criptografia e descriptografia, com certeza.
DOK
Você não precisa ignorar a tabela rainbow de tamanho decente - essa tabela também torna o salt criptografado discutível, pois pode descriptografar o hash salgado e ser usado novamente para descriptografar o hash original. A boa notícia é que a mesa provavelmente levaria séculos para ser criada.
abordagem de
O que me impressiona é que não estou totalmente certo de que uma mesa arco-íris desse tamanho levaria tanto tempo para ser criada. Ele é uma ideia maluca, pegue uma plataforma de computação distribuída como o Kraken (realmente é meio que isso) para gerá-la. Quanto tempo demoraria então?
kemiller2002,
3
@Kevin: SHA1 retorna uma string hexadecimal de 40 caracteres, portanto, há 40 ^ 16 valores de retorno possíveis. Supondo que um único computador possa calcular 1000 hashes a cada segundo, calculo que 1 milhão de computadores levariam cerca de 10 bilhões de anos para gerar uma tabela arco-íris capaz de determinar uma string desse tamanho.
próximo de
1 boa pergunta e você lê bem. Acho que você deu uma resposta errada a esta pergunta. O deve ser sempre um segredo porque o hash não pode ser quebrado até que seja obtido. Você deve ler sobre CWE-760 ( cwe.mitre.org/data/definitions/760.html )
rook

Respostas:

45

A resposta aqui é perguntar a si mesmo do que você realmente está tentando se proteger. Se alguém tiver acesso ao seu banco de dados, então essa pessoa terá acesso aos sais criptografados e provavelmente terá acesso ao seu código também. Com tudo isso eles poderiam descriptografar os sais criptografados? Nesse caso, a criptografia é praticamente inútil de qualquer maneira. O salt realmente está lá para fazer isso, de forma que não seja possível formar uma tabela de arco-íris para quebrar seu banco de dados de senhas inteiro de uma vez se ele for invadido. Desse ponto de vista, desde que cada sal seja único, não há diferença, um ataque de força bruta seria necessário com seus sais ou os sais criptografados para cada senha individualmente.

aproximar
fonte
Meio novo para esses conceitos. Portanto, pode parecer uma pergunta ingênua, mas não seria mais fácil formar essa tabela de arco-íris sabendo o salt para cada senha, já que você tentaria apenas uma combinação para o valor salt para cada senha possível?
stdout
A tabela ranbow de, digamos, 1000 senhas comumente usadas quebraria isso quase na mesma velocidade que apenas o hash. A única maneira de isso funcionar é se você assumir que a distribuição de suas senhas é uniforme ... e sabemos que não é
DaWNFoRCe
100

Esconder um sal é desnecessário.

Um sal diferente deve ser usado para cada hash. Na prática, isso é fácil de conseguir obtendo 8 ou mais bytes do gerador de números aleatórios de qualidade criptográfica.

De uma resposta anterior minha :

O sal ajuda a impedir ataques de dicionário pré-computados.

Suponha que um invasor tenha uma lista de senhas prováveis. Ele pode fazer o hash de cada um e compará-lo com o hash da senha de sua vítima e ver se corresponde. Se a lista for grande, isso pode levar muito tempo. Ele não quer gastar muito tempo em seu próximo alvo, então ele registra o resultado em um "dicionário" onde um hash aponta para sua entrada correspondente. Se a lista de senhas for muito, muito longa, ele pode usar técnicas como a Rainbow Table para economizar espaço.

No entanto, suponha que seu próximo alvo saltou sua senha. Mesmo se o invasor souber o que é o sal, sua tabela pré-computada não terá valor - o sal altera o hash resultante de cada senha. Ele tem que refazer o hash de todas as senhas em sua lista, anexando o salt do alvo à entrada. Cada sal diferente requer um dicionário diferente e, se sais suficientes forem usados, o invasor não terá espaço para armazenar dicionários para todos eles. Negociar espaço para economizar tempo não é mais uma opção; o invasor deve recorrer ao hash de cada senha em sua lista para cada alvo que deseja atacar.

Portanto, não é necessário guardar segredo sobre o sal. Garantir que o invasor não tenha um dicionário pré-calculado correspondente a esse sal específico é suficiente.


Depois de pensar um pouco mais sobre isso, percebi que é perigoso se enganar pensando que o sal pode estar escondido. É muito melhor presumir que o sal não pode ser escondido e projetar o sistema para ser seguro apesar disso. Eu forneço uma explicação mais detalhada em outra resposta.


No entanto, recomendações recentes do NIST encorajam o uso de um "sal" secreto adicional (já vi outras pessoas chamarem esse segredo adicional de "pimenta"). Uma iteração adicional da derivação de chave pode ser realizada usando este segredo como um sal. Em vez de aumentar a força contra um ataque de pesquisa pré-computado, essa rodada protege contra adivinhação de senha, bem como o grande número de iterações em uma boa função de derivação de chave. Este segredo não tem nenhum propósito se armazenado com a senha em hash; ele deve ser gerenciado como um segredo e isso pode ser difícil em um grande banco de dados de usuários.

Erickson
fonte
1
Esconder o sal é necessário porque o hash não pode ser quebrado até que seja obtido. Isso está relacionado a CWE-760 ( cwe.mitre.org/data/definitions/760.html )
rook
28
@ The Rook - Não, você está interpretando mal esse problema. Refere-se ao uso de sais previsíveis. Não diz nada sobre como manter o sal em segredo. Na verdade, você não pode realmente manter o segredo do sal sem usar outro segredo ... Nesse caso, por que você não usaria o segundo segredo como o sal? Usar o nome de usuário como um sal é ruim porque é provável que vários sistemas compartilhem o mesmo nome de usuário, tornando mais vantajoso construir uma tabela para esse sal específico. Sais aleatórios são os melhores, mas não precisam ser mantidos em segredo.
Erickson
1
@erickson, acho que você está misturando terminologia aqui. Os sais não impedem os ataques de dicionário, a menos que estejam ocultos. Muitos sais são armazenados abertamente. E se você conhece o sal, seu ataque de dicionário só é retardado pelo tempo que leva para acrescentar o sal ao seu termo do dicionário :) Os sais impedem as pesquisas nas tabelas do Rainbow .... que são muito rápidas. Se o invasor conhece o seu salt, você não está protegido contra um ataque de dicionário. Se o invasor não conhece o seu sal, você está protegido de um ataque de dicionário e ele deve usar um ataque de força bruta.
Ultratrunks
4
@Ultratrunks Sim, esclareço algumas das minhas respostas sobre este tópico, usando o termo "ataques de dicionário pré-computado". Mais geral do que as tabelas Rainbow, refere-se a qualquer estrutura que permite uma pesquisa reversa de um texto simples usando seu hash como chave. Independentemente dos termos que você escolher, meu explica explicitamente que o objetivo do sal é derrotar as tabelas Rainbow e mecanismos semelhantes. Você deve sempre presumir que o invasor conhece o sal. Se fosse possível mantê-lo em segredo, você não precisaria fazer o hash da senha.
Erickson
3

Meu entendimento de "sal" é que ele torna o cracking mais difícil, mas não tenta ocultar os dados extras. Se você está tentando obter mais segurança tornando o salt "secreto", então você realmente quer mais bits em suas chaves de criptografia.

gbarry
fonte
3

A segunda abordagem é apenas um pouco mais segura. Os sais protegem os usuários de ataques de dicionário e de tabelas de arco-íris. Eles tornam mais difícil para um invasor ambicioso comprometer todo o seu sistema, mas ainda são vulneráveis ​​a ataques que se concentram em um usuário do sistema. Se você usar informações disponíveis publicamente, como um número de telefone, e o invasor ficar sabendo disso , você salvou-o de uma etapa do ataque. Claro que a questão é discutível se o invasor obtém todo o seu banco de dados, com sais e tudo.

EDITAR: Depois de reler esta resposta e alguns dos comentários, me ocorre que parte da confusão pode ser devido ao fato de que estou apenas comparando os dois casos muito específicos apresentados na pergunta: sal aleatório vs. sal não aleatório. A questão de usar um número de telefone como um sal é discutível se o invasor obtém todo o banco de dados, e não a questão de usar um sal.

Bill the Lizard
fonte
Como eles se protegem contra ataques de dicionário?
aproxima-se de
Forçando o invasor a fazer um novo dicionário para cada combinação de senha + sal. Sem sal, um dicionário pode ser usado em toda a tabela de senhas.
Bill the Lizard,
"É claro que a questão é discutível se o invasor consegue seu banco de dados inteiro, com sais e tudo." Não é por isso que o sal é criptografado?
Patrick McElhaney,
1
@Bill: Você acabou de descrever uma mesa arco-íris. Um ataque de dicionário é quando eu pego palavras normais e tento me autenticar com elas. É uma força bruta com um espaço de resposta bastante reduzido. Nenhum hash defende contra a força bruta.
abordagem de
Nunca ouvi falar dessa prática, mas não sou um especialista em segurança. Parece que criptografar sais únicos adicionaria uma camada extra de proteção contra ataques de rainbow table.
Bill the Lizard,
3

... algo como um nome de usuário ou número de telefone para adicionar o hash. ...

Minha pergunta é se a segunda abordagem é realmente necessária? Posso entender de uma perspectiva puramente teórica que é mais seguro do que a primeira abordagem, mas e do ponto de vista prático?

Do ponto de vista prático, um sal é um detalhe de implementação. Se você alguma vez alterar a forma como as informações do usuário são coletadas ou mantidas - e os nomes de usuário e números de telefone às vezes mudam, para usar seus exemplos exatos -, você pode ter comprometido sua segurança. Você deseja que essa mudança voltada para o exterior tenha preocupações de segurança muito mais profundas?

Interromper a exigência de que cada conta tenha um número de telefone precisa envolver uma análise completa de segurança para garantir que você não abriu essas contas para comprometer a segurança?

Anon
fonte
2
Sem mencionar que se você está usando alguma informação arbitrária do usuário, quando eles alteram essas informações, você precisa inserir a senha novamente para que possa criptografá-la novamente com o novo sal.
Treborbob
3

Um sal escondido não é mais sal. É pimenta. Tem seu uso. É diferente do sal.

Pepper é uma chave secreta adicionada à senha + salt que transforma o hash em um HMAC (código de autenticação de mensagem baseado em Hash). Um hacker com acesso à saída do hash e ao salt pode teoricamente adivinhar a força bruta de uma entrada que irá gerar o hash (e, portanto, passar na validação na caixa de texto da senha). Ao adicionar pimenta, você aumenta o espaço do problema de maneira criptograficamente aleatória, tornando o problema intratável sem hardware sério.

Para mais informações sobre pimenta, clique aqui .

Veja também hmac .

John Wu
fonte
2

Aqui está um exemplo simples que mostra por que é ruim ter o mesmo sal para cada hash

Considere a seguinte tabela

UserId  UserName,   Password
     1  Fred       Hash1 =  Sha(Salt1+Password1)    
     2  Ted        Hash2 =  Sha(Salt2+Password2)    

Caso 1, quando salt 1 é o mesmo que salt2 Se Hash2 for substituído por Hash1, o usuário 2 pode fazer logon com a senha do usuário 1

Caso 2, quando o salt 1 não é o mesmo salt2 Se o Hash2 for substituído por Hash1, o usuário2 não poderá fazer logon com a senha do usuário 1.

Charles Faiga
fonte
Não estamos usando o mesmo hash para cada conta, estamos usando o mesmo tipo de informação para cada hash. Por exemplo, o sal para uma conta é o número de
telefone
Eu sei que isso é muito tempo depois, mas ... você não pode contar com sais para se proteger contra esse tipo de ataque. Devemos presumir que um invasor sabe tudo sobre o sistema de autenticação, exceto o segredo (ou seja, senha). Portanto, devemos assumir que o invasor sabe a) o que estamos usando como sal (na maioria das vezes isso é armazenado no mesmo banco de dados e tabela em texto simples) eb) como estamos fazendo hash com o sal (ou seja, anexando, hashing duas vezes, etc). Se o usuário tiver a capacidade de trocar os hashes, devemos assumir que ele também pode trocar o salt. Sais não vão ajudar aqui.
Dave Satch
1

Existem duas técnicas, com objetivos diferentes:

  • O "sal" é usado para fazer com que duas senhas iguais sejam criptografadas de forma diferente. Dessa forma, um invasor não pode usar com eficiência um ataque de dicionário contra uma lista inteira de senhas criptografadas.

  • O "segredo" (compartilhado) é adicionado antes do hash de uma mensagem, para que um invasor não possa criar suas próprias mensagens e aceitá-las.

Javier
fonte
0

Tenho tendência a esconder o sal. Eu uso 10 bits de salt acrescentando um número aleatório de 1 a 1024 ao início da senha antes de fazer o hash. Ao comparar a senha que o usuário inseriu com o hash, faço um loop de 1 a 1024 e tento todos os valores possíveis de salt até encontrar a correspondência. Isso leva menos de 1/10 de segundo. Tive a ideia de fazer dessa forma a partir do PHP password_hash e password_verify . No meu exemplo, o "custo" é 10 para 10 bits de sal. Ou pelo que outro usuário disse, "sal" oculto é chamado de "pimenta". O salt não é criptografado no banco de dados. É brutamente forçado a sair. Isso tornaria a tabela de arco-íris necessária para reverter o hash 1000 vezes maior. Eu uso o sha256 porque é rápido, mas ainda é considerado seguro.

Russell Hankins
fonte
Portanto, se minha senha for "345678" e o sal aleatório que você anexar for, digamos, "12". Se alguém inserir "45678" como minha senha. Isso parece errado de várias maneiras.
Yurippenet
-1

Na verdade, depende do tipo de ataque que você está tentando proteger seus dados.

O objetivo de um salt exclusivo para cada senha é evitar um ataque de dicionário contra todo o banco de dados de senhas.

Criptografar o sal exclusivo para cada senha tornaria mais difícil quebrar uma senha individual, sim, mas você deve pesar se há realmente um benefício. Se o atacante, por força bruta, descobrir que esta string:

Marianne2ae85fb5d

hashes para um hash armazenado no banco de dados, é realmente difícil descobrir qual parte é a passagem e qual parte é o sal?

Lucas omã
fonte
2
Se alguém forçar uma senha impossível de adivinhar, eu diria que você está maluco de qualquer maneira, porque aparentemente eles têm uma tecnologia em que ninguém pensou ainda.
Instance Hunter