Como o salt da senha ajuda contra um ataque da tabela do arco-íris?

220

Estou tendo problemas para entender o propósito de um sal em uma senha. Entendo que o uso principal é dificultar um ataque à mesa do arco-íris. No entanto, os métodos que eu vi para implementar isso não parecem realmente tornar o problema mais difícil.

Eu já vi muitos tutoriais sugerindo que o sal seja usado da seguinte maneira:

$hash =  md5($salt.$password)

O raciocínio é que o hash agora mapeia não a senha original, mas uma combinação da senha e do salt. Mas diga$salt=foo e $password=bare $hash=3858f62230ac3c915f300c664312c63f. Agora, alguém com uma tabela de arco-íris poderia reverter o hash e criar a entrada "foobar". Eles poderiam tentar todas as combinações de senhas (f, fo, foo, ... oobar, obar, bar, ar, ar). Pode demorar mais alguns milissegundos para obter a senha, mas não muito mais.

O outro uso que eu vi é no meu sistema linux. Na / etc / shadow, as senhas com hash são realmente armazenadas com o salt. Por exemplo, um sal de "foo" e senha de "bar" iria botar a este: $1$foo$te5SBM.7C25fFDu6bIRbX1. Se um hacker conseguiu, de alguma forma, colocar as mãos nesse arquivo, não vejo a que finalidade o sal serve, já que o hash reverso te5SBM.7C25fFDu6bIRbXé conhecido por conter "foo".

Obrigado por qualquer luz que alguém possa lançar sobre isso.

EDIT : Obrigado pela ajuda. Para resumir o que eu entendo, o salt torna a senha com hash mais complexa, tornando muito menos provável a existência em uma tabela arco-íris pré-computada. O que eu entendi errado antes foi que eu estava assumindo que uma tabela arco-íris existia para TODOS os hashes.

Rico
fonte
Além disso, atualizado aqui - o uso do hash MD5 não é mais uma prática recomendada. stackoverflow.com/questions/12724935/salt-and-passwords
StuartLC:
Obrigado pela edição. Eu tinha a mesma dúvida que agora está esclarecida. Portanto, o objetivo do 'Salt' é realmente tornar altamente improvável que uma tabela Rainbow contenha o hash da senha adulterada (salgada), em primeiro lugar. : D
Vaibhav

Respostas:

237

Um sal público não tornará os ataques de dicionário mais difíceis ao quebrar uma única senha. Como você apontou, o invasor tem acesso à senha com hash e ao salt; portanto, ao executar o ataque do dicionário, ele pode simplesmente usar o salt conhecido ao tentar decifrar a senha.

Um sal público faz duas coisas: torna mais demorado decifrar uma grande lista de senhas e torna inviável o uso de uma tabela arco-íris.

Para entender o primeiro, imagine um único arquivo de senha que contenha centenas de nomes de usuário e senhas. Sem um sal, eu poderia calcular "md5 (tentativa [0])" e depois percorrer o arquivo para ver se esse hash aparece em qualquer lugar. Se houver sais, devo calcular "md5 (sal [a]. Tentativa [0])", comparar com a entrada A e, em seguida, "md5 (sal [b]. Tentativa [0])", comparar com a entrada B Agora tenho nmuito trabalho a fazer, onde nestá o número de nomes de usuário e senhas contidos no arquivo.

Para entender o segundo, você precisa entender o que é uma tabela arco-íris. Uma tabela arco-íris é uma grande lista de hashes pré-calculados para senhas usadas com freqüência. Imagine novamente o arquivo de senhas sem sais. Tudo o que tenho a fazer é percorrer cada linha do arquivo, retirar a senha com hash e procurá-la na tabela do arco-íris. Eu nunca tenho que calcular um único hash. Se a pesquisa for consideravelmente mais rápida que a função hash (que provavelmente é), isso acelerará consideravelmente a quebra do arquivo.

Mas se o arquivo da senha for salgado, a tabela do arco-íris deverá conter "salt. Password" pré-hash. Se o sal for suficientemente aleatório, isso é muito improvável. Provavelmente terei coisas como "olá", "foobar" e "qwerty" na minha lista de senhas pré-hash comumente usadas (tabela arco-íris), mas não terei coisas como "jX95psDZhello" ou "LPgB0sdgxfoobar" ou "dZVUABJtqwerty" pré-calculados. Isso tornaria a mesa arco-íris proibitivamente grande.

Portanto, o salt reduz o invasor de volta a uma computação por linha por tentativa, que, quando associada a uma senha suficientemente longa e aleatória, é (geralmente falando) invencível.

Ross
fonte
15
Não sei ao certo o que disse na minha resposta para sugerir que sim.
Ross
2
erickson, acho que a edição foi confusa - não acho que a maioria das pessoas considere um ataque de tabela arco-íris como uma espécie de ataque de dicionário. Deixe-me saber se há algo específico que você acha confuso na minha resposta e tentarei corrigi-lo.
Ross Ross
Eu gostaria que um poderia dar mais do que um voto positivo! Especialmente para o primeiro parágrafo. Isso soma uma lo todos IMHO
Cesar
5
Sei que isso é antigo, mas sua descrição das tabelas do arco-íris está incorreta. Você está descrevendo tabelas de hash. Para uma tabela arco-íris, consulte security.stackexchange.com/questions/379/… . Uma tabela de hash possui um mapeamento de 1 para 1 de senhas em hashes (como você descreve), mas as tabelas do arco-íris requerem uma função redutora que transforma um hash de volta em texto sem formatação, para depois ser repetido milhares de vezes, armazenando apenas o texto sem formatação inicial e o hash final. A pesquisa é computacionalmente mais longa que as tabelas de hash, mas 'captura' muitos textos simples por hash.
Mark Fisher
1
Esta resposta perde o fato de que não usar um salt (vinculado à criação de um hash de senha para um usuário específico) também expõe senhas duplicadas, mesmo em várias tabelas que armazenam essas senhas. No mínimo, você seria capaz de identificar senhas reutilizadas por uma pessoa, mas, ainda pior, também identificaria senhas usadas por pessoas diferentes, em bancos de dados diferentes.
Maarten Bodewes
119

As outras respostas parecem não abordar seus mal-entendidos sobre o tópico, então aqui vai:

Dois usos diferentes de sal

Eu já vi muitos tutoriais sugerindo que o sal seja usado da seguinte maneira:

$hash = md5($salt.$password)

[...]

O outro uso que eu vi é no meu sistema linux. Na / etc / shadow, as senhas com hash são realmente armazenadas com o salt.

Você sempre precisa armazenar o salt com a senha, pois, para validar o que o usuário digitou no seu banco de dados de senhas, é necessário combinar a entrada com o salt, fazer o hash e compará-lo com o hash armazenado.

Segurança do hash

Agora, alguém com uma tabela de arco-íris poderia reverter o hash e criar a entrada "foobar".

[...]

já que o hash reverso de te5SBM.7C25fFDu6bIRbX é conhecido por conter "foo".

Não é possível reverter o hash como tal (pelo menos em teoria). O hash de "foo" e o hash de "saltfoo" não têm nada em comum. Alterar um bit na entrada de uma função de hash criptográfico deve alterar completamente a saída.

Isso significa que você não pode construir uma tabela arco-íris com as senhas comuns e depois "atualizá-la" com algum sal. Você deve levar o sal em consideração desde o início.

Essa é toda a razão pela qual você precisa de uma tabela arco-íris em primeiro lugar. Como você não pode obter a senha do hash, pré-calcula todos os hashes das senhas usadas mais prováveis ​​e, em seguida, compara seus hashes com os hashes.

Qualidade do sal

Mas diga $salt=foo

"foo" seria uma escolha extremamente pobre de sal. Normalmente você usaria um valor aleatório, codificado em ASCII.

Além disso, cada senha tem seu próprio sal, diferente (espero) de todos os outros sais no sistema. Isso significa que o invasor deve atacar cada senha individualmente, em vez de ter a esperança de que um dos hashes corresponda a um dos valores em seu banco de dados.

O ataque

Se um hacker conseguiu, de alguma forma, colocar as mãos nesse arquivo, não vejo a que finalidade serve o sal,

Um ataque de tabela arco-íris sempre precisa /etc/passwd(ou qualquer banco de dados de senhas usado), ou então como você compararia os hashes na tabela arco-íris com os hashes das senhas reais?

Quanto ao objetivo: digamos que o invasor queira criar uma tabela arco-íris para 100.000 palavras em inglês e senhas comuns usadas com frequência (pense em "segredo"). Sem sal, ela teria que pré-calcular 100.000 hashes. Mesmo com o tradicional sal UNIX de 2 caracteres (cada uma é uma das 64 opções [a–zA–Z0–9./]:), ela teria que calcular e armazenar 4.096.000.000 de hashes ... uma melhoria bastante.

Comunidade
fonte
2
Resposta muito boa. Isso me ajudou a entender as coisas muito melhor. +1
wcm
Se um hacker tivesse acesso ao salt e como ele era usado na função hash, eles não poderiam simplesmente usá-lo para gerar uma tabela de hashes salgados e comparar esses hashes com a tabela rainbow?
Jonny
5
@ Jonny não existe "o sal". o ponto principal é que o salt é diferente para cada entrada de senha.
86

A idéia do sal é tornar muito mais difícil adivinhar com força bruta do que uma senha normal baseada em caracteres. As tabelas do arco-íris geralmente são criadas com um caractere especial definido em mente e nem sempre incluem todas as combinações possíveis (embora possam).

Portanto, um bom valor de sal seria um número inteiro aleatório de 128 bits ou mais. É isso que faz com que os ataques à tabela do arco-íris falhem. Ao usar um valor de sal diferente para cada senha armazenada, você também garante que uma tabela arco-íris criada para um valor de sal específico (como poderia ser o caso se você é um sistema popular com um único valor de sal) não lhe dá acesso a todos senhas de uma só vez.

Carl Seleborg
fonte
1
+1: o sal pode ser uma parte do resumo hexadecimal de alguma sequência aleatória criada pelo gerador de números aleatórios. Cada bit é aleatório.
S.Lott
5
"As tabelas do arco-íris são uma forma de ataque de dicionário que desiste de velocidade para economizar espaço de armazenamento". - na verdade, é o contrário, uma boa tabela arco-íris pode assumir GB para armazenar, a fim de economizar tempo re-hash de todos os valores possíveis.
Avid
2
Concordo - @erickson, acho que sua edição está errada lá. Uma tabela arco-íris requer grandes quantidades de armazenamento, mas facilita a obtenção da mensagem por trás do hash.
1911 Carl Seleborg
3
Bem, vocês dois estão certos. Comparadas a um ataque de dicionário padrão, as tabelas rainbow sacrificam a velocidade para economizar espaço de armazenamento. Por outro lado, em comparação com um ataque de força bruta, as tabelas arco-íris usam (muito) espaço para ganhar velocidade. Hoje, as tabelas do arco-íris são quase sinônimo de dicionário ...
Rasmus Faber
... ataques, mas você não precisa de tabelas arco-íris para ataques de dicionário.
Rasmus Faber
35

Mais uma ótima pergunta, com muitas respostas bem pensadas - +1 a SO!

Um pequeno ponto que eu não vi explicitamente mencionado é que, adicionando um sal aleatório a cada senha, você praticamente garante que dois usuários que escolheram a mesma senha produzirão hashes diferentes.

Por que isso é importante?

Imagine o banco de dados de senhas em uma grande empresa de software no noroeste dos EUA. Suponha que ele contenha 30.000 entradas, das quais 500 possuem a senha em tela azul . Suponha ainda que um hacker consiga obter essa senha, digamos, lendo-a em um email do usuário ao departamento de TI. Se as senhas não tiverem sal, o hacker poderá encontrar o valor do hash no banco de dados e simplesmente corresponder ao padrão para obter acesso às outras 499 contas.

Salgar as senhas garante que cada uma das 500 contas tenha um único (salt + senha), gerando um hash diferente para cada uma delas e, assim, reduzindo a violação a uma única conta. E esperemos, com toda probabilidade, que qualquer usuário ingênuo o suficiente para escrever uma senha em texto sem formatação em uma mensagem de email não tenha acesso à API não documentada para o próximo SO.

Adam Liss
fonte
O mesmo para dois usuários que escolhem uma senha diferente e é provável que eles tenham a mesma senha com hash armazenada no banco de dados. (Inútil ... eu sei)
Ant
15

Eu estava procurando por um bom método para aplicar sais e encontrei este excelente artigo com código de exemplo:

http://crackstation.net/hashing-security.htm

O autor recomenda o uso de sais aleatórios por usuário, para que o acesso a um sal não torne fácil a quebra de toda a lista de hashes.

Para armazenar uma senha:

  • Gere um longo sal aleatório usando um CSPRNG.
  • Anexe o salt à senha e faça o hash com uma função padrão de hash criptográfico, como SHA256.
  • Salve o salt e o hash no registro do banco de dados do usuário.

Para validar uma senha:

  • Recupere o sal e o hash do usuário do banco de dados.
  • Anexe o salt à senha fornecida e faça o hash usando a mesma função de hash.
  • Compare o hash da senha fornecida com o hash do banco de dados. Se eles corresponderem, a senha está correta. Caso contrário, a senha está incorreta.
MytyMyky
fonte
3
O Hashcat pode experimentar quase 17 bilhões de hashes SHA256 salgados por segundo usando um único PC. O autor do artigo vinculado fala sobre isso no título "Tornando a quebra de senhas mais difícil: funções de hash lento". scrypt, bcrypt e PBKDF2 são boas escolhas e valem mais que os ciclos extras de CPU no servidor IMHO. Atualmente, o Argon2 é o estado da arte, mas não é tão testado em batalha quanto os outros.
kgriffs
12

A razão pela qual um sal pode fazer um ataque à mesa arco-íris falhar é que, para n bits de sal, a mesa arco-íris deve ser 2 ^ n vezes maior que o tamanho da mesa sem o sal.

Seu exemplo de usar 'foo' como sal pode tornar a mesa do arco-íris 16 milhões de vezes maior.

Dado o exemplo de Carl de um sal de 128 bits, isso torna a tabela 2 ^ 128 vezes maior - agora é grande - ou, em outras palavras, quanto tempo leva para que alguém tenha um armazenamento portátil tão grande?

quamrana
fonte
8
Mesmo se você usar um único elétron para armazenar um pouco, levará um bom tempo até alguém produzir armazenamento portátil com essa capacidade ... a menos que você considere um sistema solar movendo-se através da galáxia como portátil.
Erickson
10

A maioria dos métodos para quebrar a criptografia baseada em hash depende de ataques de força bruta. Um ataque do arco-íris é essencialmente um ataque de dicionário mais eficiente; foi projetado para usar o baixo custo do armazenamento digital para permitir a criação de um mapa de um subconjunto substancial de senhas possíveis para hashes e facilitar o mapeamento reverso. Esse tipo de ataque funciona porque muitas senhas tendem a ser bastante curtas ou usam um dos poucos padrões de formatos baseados em palavras.

Esses ataques são ineficazes no caso em que as senhas contêm muito mais caracteres e não estão em conformidade com formatos comuns baseados em palavras. Um usuário com uma senha forte para começar não ficará vulnerável a esse estilo de ataque. Infelizmente, muitas pessoas não escolhem boas senhas. Mas há um compromisso: você pode melhorar a senha de um usuário adicionando lixo aleatório a ela. Portanto, agora, em vez de "hunter2", sua senha pode se tornar efetivamente "hunter2908! Fld2R75 {R7 /; 508PEzoz ^ U430", que é uma senha muito mais forte. No entanto, como agora você precisa armazenar esse componente de senha adicional, isso reduz a eficácia da senha composta mais forte. Acontece que ainda existe um benefício líquido para esse esquema, já que agora cada senha, mesmo as mais fracas, não são mais vulneráveis ​​à mesma tabela de hash / arco-íris pré-calculada. Em vez disso, cada entrada de hash da senha é vulnerável apenas a uma tabela de hash exclusiva.

Digamos que você tenha um site com requisitos de força de senha fracos. Se você não usar salt de senha, todos os seus hashes estarão vulneráveis ​​a tabelas de hash pré-calculadas, alguém com acesso a seus hashes teria acesso às senhas para uma grande porcentagem de seus usuários (no entanto, muitas usavam senhas vulneráveis, o que seria uma percentagem substancial). Se você usar um salt de senha constante, as tabelas de hash pré-calculadas não serão mais valiosas; portanto, alguém teria que gastar tempo para calcular uma tabela de hash personalizada para esse salt, mas poderia fazê-lo de forma incremental, porém, tabelas de computação que cobrem permutações cada vez maiores do espaço do problema. As senhas mais vulneráveis ​​(por exemplo, senhas simples baseadas em palavras, senhas alfanuméricas muito curtas) seriam decifradas em horas ou dias, senhas menos vulneráveis ​​seriam decifradas após algumas semanas ou meses. Com o passar do tempo, um invasor obteria acesso a senhas para uma porcentagem cada vez maior de seus usuários. Se você usar um salt exclusivo para cada senha, levaria dias ou meses para obter acesso a cada uma dessas senhas vulneráveis.

Como você pode ver, quando você passa de um sal sem sal para um sal constante para um sal único, impõe um aumento de várias ordens de magnitude no esforço de quebrar senhas vulneráveis ​​a cada etapa. Sem um salt, as senhas mais fracas de seus usuários são trivialmente acessíveis, com um sal constante essas senhas fracas são acessíveis a um invasor determinado, com um salt único, o custo de acessar senhas é tão alto que apenas o invasor mais determinado pode obter acesso para um pequeno subconjunto de senhas vulneráveis ​​e, em seguida, apenas com grandes custos.

Qual é precisamente a situação em que você se encontra. Você nunca pode proteger completamente os usuários de uma escolha incorreta de senhas, mas pode aumentar o custo de comprometer as senhas de seus usuários a um nível que torne comprometedor mesmo a senha de um usuário proibitivamente cara.

Cunha
fonte
3

Um dos objetivos da salga é derrotar tabelas de hash pré-computadas. Se alguém tiver uma lista de milhões de hashes pré-calculados, não poderá procurar US $ 1 $ foo $ te5SBM.7C25fFDu6bIRbX1 em sua tabela, mesmo sabendo o hash e o sal. Eles ainda terão que forçar a força bruta.

Outro objetivo, como Carl S menciona, é tornar o bruto forçar uma lista de hashes mais cara. (dê a todos diferentes sais)

Ambos os objetivos ainda são alcançados, mesmo que os sais sejam públicos.

recursivo
fonte
1

Até onde eu sei, o sal é destinado a dificultar os ataques de dicionário.

É um fato conhecido que muitas pessoas usam palavras comuns para senhas em vez de seqüências aparentemente aleatórias.

Assim, um hacker poderia usar isso a seu favor, em vez de usar apenas força bruta. Ele não procurará senhas como aaa, aab, aac ... mas usará palavras e senhas comuns (como nomes do senhor dos anéis!;))

Portanto, se minha senha for Legolas, um hacker pode tentar fazer isso e adivinhar com "poucas" tentativas. No entanto, se saltarmos a senha e ela se tornar fooLegolas, o hash será diferente; portanto, o ataque ao dicionário não terá êxito.

Espero que ajude!

rgargente
fonte
-2

Suponho que você esteja usando a função PHP --- md5 () e variáveis ​​$ precedidas ---, então você pode tentar ler este artigo HOWTO da Senha da Sombra Especialmente no parágrafo 11.

Além disso, você tem medo de usar algoritmos de compilação de mensagens, pode tentar algoritmos de criptografia reais, como os fornecidos pelo módulo mcrypt , ou algoritmos de compilação de mensagens mais fortes, como os que fornecem o módulo mhash (sha1, sha256 e outras).

Eu acho que um algoritmo mais forte de digestão de mensagens é obrigatório. Sabe-se que o MD5 e o SHA1 estão tendo problemas de colisão.

daniel
fonte