Onde você guarda suas cordas de sal?

250

Eu sempre usei uma string salt adequada por entrada ao fazer hash de senhas para armazenamento de banco de dados. Para minhas necessidades, armazenar o sal no banco de dados ao lado da senha com hash sempre funcionou bem.

No entanto, algumas pessoas recomendam que o sal seja armazenado separadamente do banco de dados. O argumento deles é que, se o banco de dados estiver comprometido, um invasor ainda poderá criar uma tabela arco-íris, levando em consideração uma sequência de sal específica, a fim de quebrar uma conta de cada vez. Se essa conta tiver privilégios de administrador, talvez ele nem precise quebrar nenhuma outra.

Do ponto de vista da segurança, vale a pena armazenar sais em um local diferente? Considere um aplicativo da web com o código do servidor e o banco de dados na mesma máquina. Se os sais forem armazenados em um arquivo simples nessa máquina, é provável que, se o banco de dados for comprometido, o arquivo de sais também será.

Existem soluções recomendadas para isso?

friedo
fonte
9
Se houver um lugar em que você possa armazenar o sal que o invasor não pode obter, você também deve armazenar as senhas também. Mas por que não usar um sal diferente para cada senha?
jrockway
8
Ele está usando um sal diferente para cada senha, jrockway.
2200 Amber
9
Qual é o tamanho dos seus sais? Seus sais devem ser grandes o suficiente (32 bits?) Para que praticamente não haja chance de uma mesa arco-íris ter sido pré-computada para isso.
M. Dudley
@emddudley hoje em dia, eu tenho o hábito de usar um número inteiro de 64 bits como sal, mas não há razão para que eu não os possa prolongar.
Friedo 03/08/2009
10
Autor do PWDTK aqui sourceforge.net/projects/pwdtknet , sinceramente não me preocuparia e armazenaria sal no mesmo banco de dados que a senha. Você sempre deve presumir que o sal é conhecido por um invasor de qualquer maneira, portanto seu foco deve estar no uso de um sal GRANDE CRIPPTO-RANDOM e na execução de alongamentos de tecla suficientes (iterações no PBKDF2) para que seja inviável fazer apenas uma tabela arco-íris para um sal conhecido. Honestamente, o que você está tentando alcançar colocando o sal em outro lugar é "Segurança por Obscuridade" e geralmente não serve para nada quando você olha coisas como outro servidor que pode ficar inativo.
Thashiznets

Respostas:

259

O ponto das tabelas arco-íris é que elas são criadas com antecedência e distribuídas em massa para economizar tempo de cálculo para outras pessoas - leva tanto tempo para gerar tabelas arco-íris em tempo real quanto seria necessário apenas quebrar a senha + a combinação de sal diretamente (desde efetivamente o que está sendo feito ao gerar tabelas arco-íris é pré-executar os cálculos para forçar brutalmente o hash); portanto, o argumento de que, conhecendo o sal, alguém poderia "gerar uma tabela arco-íris" é espúrio.

Não há nenhum ponto real em armazenar sais em um arquivo separado, contanto que eles sejam por usuário - o ponto principal é simplesmente fazê-lo para que uma tabela arco-íris não possa quebrar todas as senhas no banco de dados.

Âmbar
fonte
17
Acordado. O modelo de ameaça contra o qual você está protegendo armazenando o salt separadamente é um usuário que, de alguma forma, pode acessar o salt no DB por meios nefastos, mas não o hash (no DB). E que essa pessoa começará a calcular uma tabela arco-íris com antecedência, assumindo que será capaz de encontrar o hash mais tarde. Não é impossível, mas também não vale o esforço de engenharia para se defender contra essa única avenida de ataque.
21430 Tom Ritter
Bom post, eu queria saber a mesma coisa. Nunca pensei em um sal por usuário. Estava pensando que um único sal funcionaria para todos os usuários. Que tal um salt armazenado como um arquivo XML carregado pelo App Server? ou talvez de alguma forma codificado em um servlet?
22412 jigzat
9
@Jigzat - Salgar é inútil se você não tiver um sal separado para cada usuário. O objetivo dos sais é tornar a quebra dos hashes uma tarefa separada para cada senha de usuário; se o sal é o mesmo para todos eles, esse não é o caso.
28412 Amber
3
@ TomRitter não é o único caso. você assume que todas as senhas são complicadas. alguns atacantes podem pegar o sal e o hash e verificar apenas as 10.000 senhas mais comuns. Dessa forma, eles receberão um número decente de pessoas. se, no entanto, eles não tiverem acesso ao salt, isso é semelhante ao usuário ter uma senha mais longa e mais segura. agora, qual a probabilidade de o banco de dados salt permanecer seguro enquanto o banco de dados de senhas é roubado está em debate, mas isso é uma questão à parte.
precisa saber é o seguinte
@ Amber, acredito que o TomRitter está correto. Armazenar o sal separadamente significa a diferença entre forçar um invasor a usar um ataque de força bruta versus um ataque de dicionário mais fácil. Se você conhece o sal, basta adicioná-lo durante uma série de ataques no dicionário do moinho. Se você pode defender 100% do seu sal, pode simplesmente usar o mesmo sal e forçar os atacantes a forçar tudo (até mesmo para usuários que usam "senha" como senha). Mas você pode defender o seu sal ... provavelmente não. Portanto, é melhor reduzir os pontos de falha armazenando-o próximo ao hash e impor regras de senha mais fortes.
Ultratrunks
35

Vou fornecer uma visão um pouco diferente sobre isso.

Eu sempre guardo o sal misturado com o hash da senha salgada.

Por exemplo, colocarei a primeira metade do sal antes do hash salgado da senha e a última metade do sal após o hash salgado da senha. O aplicativo está ciente desse design para poder buscar esses dados e obter o hash salt e salted-password.

Minha justificativa para essa abordagem:

Se os dados de senha / hash forem comprometidos e caírem nas mãos de um invasor, o invasor não saberá o que é o sal olhando os dados. Dessa maneira, um invasor praticamente não pode executar um ataque de força bruta para obter uma senha que corresponda ao hash, pois ele não conhece o hash e não tem como saber quais partes dos dados são partes do sal, ou partes do hash de senha salgada (a menos que ele conheça a lógica de autenticação do seu aplicativo ).

Se o hash da senha salgada for armazenado como está, um ataque de força bruta poderá ser executado para obter uma senha que, quando salgada e com hash, produz os mesmos dados que o hash da senha com sal.

No entanto, por exemplo, mesmo que o hash da senha salgada tenha sido armazenado como está, mas pré-pendente com um único byte aleatório, desde que o invasor não saiba que esse primeiro byte deve ser descartado, isso também aumentaria a dificuldade de ataque. Seu aplicativo saberia descartar o primeiro byte dos dados quando usado para autenticar seu usuário.

A conclusão disso ..

1) Nunca armazene os dados que seu aplicativo de autenticação usa em sua forma exata.

2) Se possível, mantenha sua lógica de autenticação em segredo para aumentar a segurança.

Dê um passo adiante ..

Se você não pode manter em segredo a lógica de autenticação do aplicativo - muitas pessoas sabem como seus dados são armazenados no banco de dados. E suponha que você tenha decidido armazenar o hash da senha salgada misturado com o sal, com um pouco do sal precedido pelo hash da senha salgada e o restante do sal anexado.

Ao gerar o sal aleatório, você também pode decidir aleatoriamente qual proporção de sal armazenará antes / depois do hash da senha salgada.

Por exemplo, você gera um sal aleatório de 512 bytes. Você acrescenta o salt à sua senha e obtém o hash SHA-512 da sua senha salgada. Você também gera um número inteiro aleatório 200. Em seguida, armazena os primeiros 200 bytes do salt, seguidos pelo hash da senha salgada, seguido pelo restante do sal.

Ao autenticar a entrada de senha de um usuário, seu aplicativo passa a string e assume que o primeiro 1 byte dos dados é o primeiro 1 byte do salt, seguido pelo hash salgado. Este passe falhará. O aplicativo continuará usando os 2 primeiros bytes dos dados como os 2 primeiros bytes do salt e repetirá até que um resultado positivo seja encontrado após o uso dos primeiros 200 bytes como os primeiros 200 bytes do salt. Se a senha estiver incorreta, o aplicativo continuará tentando todas as permutações até que nenhuma seja encontrada.

Os profissionais dessa abordagem:

Maior segurança - mesmo que sua lógica de autenticação seja conhecida, a lógica exata é desconhecida no momento da compilação. É praticamente impossível realizar um ataque de força bruta, mesmo com o conhecimento da lógica exata. Comprimentos maiores de sal aumentarão ainda mais a segurança.

Os contras dessa abordagem:

Como a lógica exata é inferida em tempo de execução, essa abordagem é muito intensiva da CPU. Quanto maior o comprimento do sal, mais intensiva a CPU essa abordagem se torna.

A autenticação de senhas incorretas envolverá o custo mais alto da CPU. Isso pode ser contraproducente para solicitações legítimas, mas aumenta a segurança contra invasores.

Essa abordagem pode ser implementada de várias maneiras e pode ser ainda mais segura usando sais de largura variável e / ou hashes de senha salgada.

Ibraheem
fonte
9
Com sua abordagem, você está apenas adicionando um segredo ao seu processo de hash (o algoritmo que aplica o sal). Este segredo você pode adicionar muito mais fácil com a adição de uma pimenta adicionalmente ao sal, tentei apontar isso no meu tutorial . As funções de hash modernas, como o BCrypt, aplicam o sal por conta própria, usando o sal original em cada iteração, para que você não tenha controle sobre isso.
Martinstoeckli
@martinstoeckli Enquanto você está certo de que o BCrypt aplica o sal por conta própria, o armazenamento desse salt + hash depende de você como desenvolvedor. Portanto, você pode facilmente adicionar uma pimenta ao salt + hash e persistir no banco de dados. Em seguida, na recuperação subsequente, você lê o valor do banco de dados, retira o valor de pimenta e passa o valor restante para BCrypt.
PeterToTheThird
2
@ PeterToTheThird - Isso negaria a vantagem da pimenta. A pimenta adiciona um segredo do lado do servidor e só funciona enquanto permanecer em segredo (oposto ao sal). Um ataque típico é a injeção de SQL, quando alguém obtém acesso ao banco de dados, mas não ao código, uma pimenta armazenada no banco de dados será inútil. A maioria das implementações do BCrypt adicionará o salt automaticamente ao valor de hash resultante, portanto esse valor já contém o salt, o fator de custo, o algoritmo e o hash. Essa sequência pode ser armazenada em um único campo de 60 caracteres.
30813 martinstoeckli
Para adicionar, ao usar uma função de "fortalecimento de tecla" como o BCrypt, você não tem controle sobre o uso do sal. No entanto, se você quiser usar uma pimenta, basta anexá-la ao sal e usá-la como um "sal apimentado" no lugar da entrada "sal" da função hash. O "pepper" é um dado adequado que não é armazenado no banco de dados, mas incorporado no código de autenticação ou armazenado em outro local seguro. Abordei o problema de uma perspectiva genérica, usando o SHA-512 como uma função de exemplo, mas o BCrypt etc. também pode ser usado de maneira semelhante.
Ibraheem
2
@martinstoeckli - sim, a implementação real depende de qual função de hash você usa. Obviamente, você precisa levar em consideração os parâmetros e saídas da função hash ao implementar sua lógica de autenticação. Por fim, uma pimenta é apenas outra variável introduzida na sua função de hash, que não é armazenada no mesmo local que o sal e o hash.
Ibraheem 31/05
23

Geralmente, eles são anexados ao hash e armazenados no mesmo campo.

Não há necessidade de armazená-los separadamente - o objetivo é usar um sal aleatório para cada senha, para que uma única tabela do arco-íris não possa ser usada contra todo o conjunto de hashes de senha. Com sais aleatórios, um atacante deve aplicar força bruta a cada hash separadamente (ou calcular uma tabela do arco-íris para todos os sais possíveis - muito mais trabalho).

Se você tivesse um local de armazenamento mais seguro, faria sentido apenas armazenar os hashes lá.

ninguém
fonte
4
Mas o que acontece se todas as senhas com hash vazarem, incluindo o sal correspondente? Isso não é tão inseguro?
mghaoui
10
@mghaoui Mas se você quiser saber a "senha", ainda precisará construir uma Tabela Arco-Íris para cada sal, a menos que alguns dos sais sejam os mesmos.
Franklin
4

Baseado no livro Developing ASP.NET MVC 4 Web Applications de William Penberthy:

  1. O acesso aos sais armazenados em um banco de dados separado exige que os hackers invadam dois bancos de dados diferentes para obter acesso ao sal e à senha salgada. Armazená-los na mesma tabela que a senha, ou mesmo em outra tabela do mesmo banco de dados, significaria que quando os hackers obtiverem acesso ao banco de dados, eles terão acesso ao hash salt e à senha. Como a segurança inclui o processo de tornar o hacking no sistema muito caro ou demorado para valer a pena, dobrar a quantidade de acesso que um hacker precisaria obter deve tornar o sistema mais seguro.
  2. A facilidade de uso é o principal motivo para manter os sais no mesmo banco de dados que as senhas com hash. Você não precisaria garantir que dois bancos de dados estejam sempre disponíveis ao mesmo tempo e sempre sincronizados. A vantagem de ter um sal é mínima se cada usuário tiver um sal aleatório porque, embora possa facilitar a descoberta da senha de um indivíduo, a quantidade de força necessária para decifrar as senhas do sistema em geral será alta. Nesse nível de discussão, é realmente essa a expectativa: proteger as senhas. Se os hackers adquiriram uma cópia do banco de dados, os dados do aplicativo já estão comprometidos. Neste ponto, o problema é mitigar os riscos dos usuários devido ao potencial de senhas compartilhadas.
  3. O requisito de manter dois bancos de dados vinculados separados é extenso. É verdade que agrega a percepção de segurança, mas a única vantagem que oferece é que protege uma senha, um único elemento de dados. Se todos os campos no banco de dados fossem criptografados individualmente e esse mesmo sal fosse usado para isso, faria mais sentido armazená-lo separadamente dos dados, porque a segurança básica do seu sistema é aprimorada.
DaNeSh
fonte
Se o aplicativo puder se autenticar nos dois bancos de dados, não é essencialmente o mesmo que se fosse um banco de dados, se o invasor comprometeu o código do aplicativo?
John Ernest
0

O objetivo de um sal é tornar inúteis todas as tabelas do arco-íris e exigir a criação de um novo conjunto delas. Leva tanto tempo para adivinhar uma corda quanto para fazer uma mesa de arco-íris. Por exemplo, o hash SHA-256 de "senha" é 5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8. Após a adição de um salt, como "badpassword", a nova string a ser hash é "passwordbadpassword" que, devido ao efeito de avalanche, altera drasticamente a saída para 457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6.

Normalmente, o salt é apenas armazenado no mesmo banco de dados que a senha, também porque se um banco de dados for invadido, é provável que o outro também seja.

Eric Jin
fonte