Como implementar um histórico de senhas seguras

23

As senhas não devem ser armazenadas em texto sem formatação por razões óbvias de segurança: você precisa armazenar hashes e também gerar o hash com cuidado para evitar ataques à tabela do arco-íris.

No entanto, geralmente você tem o requisito de armazenar as últimas n senhas e impor complexidade mínima e alteração mínima entre as diferentes senhas (para impedir que o usuário use uma sequência como Senha_1, Senha_2, ..., Senha_ n ). Isso seria trivial com senhas de texto simples, mas como você pode fazer isso armazenando apenas hashes?

Em outras palavras: como é possível implementar um mecanismo seguro de histórico de senhas?

Wizard79
fonte
2
Relacionado: security.stackexchange.com/questions/4704/… (e BTW, esse site pode ser um local melhor para esta pergunta). Quanto a 'mudança mínima', não consigo pensar em nenhuma alternativa para gerar todas as opções que se qualificariam como 'mudança mínima' (o que pode ser MUITO dependendo da sua definição!) E comparar os hashes. Qual é a definição de 'mudança mínima'?
Kevin Vermeer
7
Armazenar as n senhas mais recentes significa apenas que o usuário escolherá uma sequência que será executada de 1 a n + 1 .
Joachim Sauer
11
Sou muito cético quanto ao fato de uma política de senha melhorar a segurança; IMHO, aumenta as chances de as pessoas recorrerem a manter sua senha em um lembrete. O link de Kevin é uma boa discussão. @KevinVermeer - você pode realmente medir a quantidade de alterações como a distância de Levenshtein ( en.wikipedia.org/wiki/Levenshtein_distance ), também conhecida como "distância de edição".
Nathan Long
5
Se sua segurança for rigorosa, você poderá gerar uma senha aleatória para o usuário, forçá-lo a usá-la e alterá-la em intervalos regulares. Dessa forma, você tem controle total sobre a senha deles.
Reactgular
2
@nathan: Armazenar senhas em um lembrete é realmente seguro. Não é possível atacar a senha, a menos que você tenha acesso físico à nota, eliminando cerca de 99% das ameaças. Coloque essa nota dentro de uma carteira ou bolsa e você basicamente precisará agredir a pessoa para obtê-la - o que significa que uma violação de segurança é identificada e pode ser mitigada.
mattnz

Respostas:

22

Armazene os hashes e verifique uma senha inserida nesses hashes armazenados, da mesma maneira que verifica uma senha ao efetuar login. Você precisaria gerar senhas 'alternativas' a partir daquela fornecida com base em padrões numéricos para detectar suas alterações 'mínimas'.

No login, você já verifica a senha inserida com um hash, não há necessidade de armazenar a senha em texto sem formatação. O mesmo truque funciona quando se trata de alterar uma senha, basta verificar as senhas geradas inseridas e com 'alteração mínima' nos hashes históricos. Se a nova senha for satisfatória, mova o hash da senha atual para o conjunto histórico e substitua-o por um novo hash para a nova senha.

Martijn Pieters
fonte
Assim, se o usuário digita Password6 eu deveria detectar a parte numérica, e tentar por exemplo Password4 , Password5 , Password7 , e assim por diante. Isso está correto?
Wizard79
4
@ Lorenzo: Correto. A geração de alternativas pode ser tão complexa quanto você desejar, apenas certifique-se de encontrar a troca certa entre complexidade e risco (não deixe seus usuários esperarem 5 minutos enquanto verifica todas as possibilidades com a possibilidade de risco).
Martijn Pieters
Não tenho certeza se sugerir incrementar o número no final é uma boa sugestão a ser feita aos usuários - isso é um pouco previsível. E fica exponencialmente mais ainda se você estiver dizendo aos usuários para fazê-lo.
Wyatt Barnett
2
@ WyattBarnett: Ninguém está dizendo aos usuários para fazê-lo. O objetivo é detectar os usuários que estão fazendo isso e impedir que a senha 'incrementada' seja usada.
Martijn Pieters
Ah, entendi completamente algo errado aqui. Desculpe.
Wyatt Barnett
28

Quando o usuário alterar sua senha, solicite a inserção da senha anterior. Agora você tem acesso a duas senhas de texto sem formatação, mesmo que não esteja armazenando senhas de texto sem formatação no seu banco de dados.

Execute as verificações desejadas nessas duas senhas. Isso não impedirá que o usuário alterne entre duas senhas (com um sufixo - você pode impedir a alternância direta de acordo com as sugestões de outras respostas), mas impedirá os casos mais flagrantes.

Brian
fonte
Bem, essa é certamente uma solução inteligente, se você não tiver necessidade de testar contra n senhas anteriores, no entanto, a sugestão de gerar as alternativas na hora certa é melhor. Mas gerar alternativas de ambas as senhas é ainda melhor!
Wizard79
2
@ Lorenzo: A idéia é que você faça um teste direto contra as senhas anteriores e um teste mais forte contra a última senha. É um compromisso.
27712 Brian
Sim. Se a senha atual é potatoSalad1e eles desejam atualizar potatoSalad2, você diz que a alteração é muito pequena porque você tem as duas senhas de texto sem formatação naquele momento. Mas, além disso, você tem apenas hashes, e a natureza dos hashes é que você não pode dizer se dois hashes tinham texto simples semelhante ou completamente diferente como entrada.
Nathan Long
7

para adicionar à resposta do @ martijnPieter, a alteração mínima pode ser implementada com uma força bruta curta, com base nas senhas novas e anteriores (que você tem disponível)

por exemplo, você pode iterar todas as senhas com uma distância de 1 ou 2 da nova senha e verificar se ela corresponde a uma senha antiga

mas você pode observar que isso pode reduzir a confiança dos usuários de que você está usando hash de senhas (como você está dizendo essencialmente que pode obter uma senha anterior para rejeitar uma nova senha)

catraca arrepiante
fonte
Mas existem muitas sequências com distâncias maiores de Hamming, como fevereiro de 2012 -> março de 2012 ou sex-09-28-12 -> ter-11-27-12 (datas), senha_Alpha -> senha_Beta, senha_Beta, passagem_1111 -> passagem_2222, passagem_qwer, passagem_tyui, Passe, _op [] ou Onze -> Doze (sistemas de contagem alternativos) ou FrankSmith -> FredJones -> FriarTuck ou raiva -> animal -> maçã (nomes em um diretório de empresa ou palavras em um dicionário) que um invasor com o as senhas anteriores poderiam adivinhar com facilidade, mas que seu algoritmo teria um tempo extremamente difícil de gerar.
Kevin Vermeer
@KevinVermeer então responsáveis por aqueles em que você gerador de variação, e aceitar que você nunca vai ter tudo
catraca aberração
+1 para reduzir a confiança. Quando vejo algo me dizendo que minha senha é muito parecida com a que usei há três meses, fico imaginando instantaneamente se eles estão sendo armazenados de forma reversível ... ou se eles têm um programador incrível. O ceticismo geralmente vence.
Tim Post
5

Este é realmente mais um adendo à resposta inteligente de @ Brian. Tiramos o chapéu também para @Martijn Pieters por adicionar detalhes sobre como forçar com força bruta as senhas antigas com base na atual e para @ratchet freak por "distância de interferência". Não estou excluindo minha resposta porque acho que fornece um plano de fundo interessante para fazer backup deles.

O armazenamento de senhas de última geração requer o uso de várias rodadas de um forte hash criptográfico unidirecional (SHA-512 +) com sal exclusivo (128 bits +) para cada usuário. Mas não fique tentado a armazenar informações adicionais sobre cada senha. Quanto mais informações você armazenar sobre cada senha, mais prejudicará a segurança do seu algoritmo de hash.

Exemplo

Considere como é fácil forçar uma senha com força bruta, se você souber:

  • Tem 7 caracteres
  • Os caracteres 3-5 são maiúsculos (4 é menor)
  • 1 e 7 são números
  • 6 é um símbolo

Um teclado dos EUA possui 95 caracteres imprimíveis, portanto, saber que a senha tem 7 caracteres gera 95 ^ 7 = 69.833.729.610.000 = 7x10 ^ 13 permutações. Se fosse realmente aleatório, levaria um ano para decifrar isso em um único processador de 3Ghz. Mas:

  • Existem apenas 26 caracteres maiúsculos e 26 minúsculos
  • Existem apenas 10 dígitos com 100 possibilidades para esses dois números
  • Existem apenas 32 símbolos

Então (corrigido graças a @Hellion):

         26^4 (charcters 2-5 are known upper or lower-case)
        x 100 (characters 1 & 7 are digits)
        x  32 (character 6 is a symbol)
         ====
1,462,323,200 possible passwords.

Isso é 50.000 vezes mais fácil de quebrar! Armazenar boas informações para evitar senhas semelhantes nesse caso levou o tempo de crack para uma senha de 7 caracteres de um ano para duas horas. A decodificação de todas as suas senhas em um poderoso desktop com vários processadores, com uma boa placa de vídeo e um pouco de paciência agora é muito viável. Espero que este exemplo simples demonstre que, quanto mais significativo você puder comparar senhas semelhantes, menos seguro será seu hash.

Importância do hash forte

Bancos de dados com senhas são roubados regularmente, com invasões gigantescas nas notícias todos os meses. Caramba, no mês passado, o estado de SC perdeu o número de seguridade social de todos - oops! Quantas dessas violações são encobertas?

Pensamento final

A coisa mais assustadora para mim é quando as pessoas escolhem a senha igual ou semelhante para vários sites, de modo que a invasão em uma só dá ao invasor acesso a todos eles. Adoraria ver um método comprovado de evitar essa situação, embora eu ache que impedir as senhas ruins mais comuns ajudaria mais do que impedir que um usuário individual reutilize sua senha ruim no mesmo site. O melhor que posso sugerir é uma política em toda a empresa para usar um gerenciador de senhas seguro que gere senhas altamente aleatórias para cada um de seus usuários e as armazene com segurança.

GlenPeterson
fonte
1
nit menor: as possibilidades de senha ainda são multiplicativas, então é (26 ^ 4) * 100 * 32 = 1.462.323.200. Se assumirmos que as possibilidades de quebra (95 ^ 7) levam um ano, a quebra desse menor número de possibilidades levará cerca de 11 minutos.
precisa
@Hellion - Opa! Obrigado por apontar isso. Eu corrigi isso.
GlenPeterson
1

Primeiro, você pode armazenar os hashes das últimas senhas "n" anteriores, para poder verificar se a nova senha duplica uma senha anterior. Você também possui o texto sem formatação da senha atual (porque eles efetuaram login ou lhe forneceram para autenticar a solicitação de alteração de senha) e a nova senha, para que você possa verificar se há alterações mínimas entre essas duas senhas.

Se (para você) for muito importante comparar diretamente essas duas senhas com as "n" senhas anteriores, será necessário armazenar essas senhas (criptografadas) para poder recuperá-las posteriormente.

Embora isso possa ser visto como uma falha de segurança, métodos de criptografia podem ser implementados para fornecer segurança suficiente.

  1. Armazene cada senha (criptografada), para as últimas "n" senhas.
  2. Armazene a data e a hora em que a senha mais recente foi criada.
  3. Armazene o hash da senha mais recente.
  4. Criptografe todas as senhas usando o hash (salgado) da senha atual e o carimbo de data e hora de criação da senha, e talvez algo como um número de conta ou endereço de email.
  5. Descriptografar e criptografar todas as senhas cada vez que uma nova senha é criada.

Então, sempre que a senha for alterada, você pode descriptografar todas as senhas antigas e fazer todos os seus testes de alteração mínima.

Agora, se alguém tivesse a senha dessa pessoa e soubesse todos os outros detalhes necessários, poderia descriptografar essas informações para essa pessoa. Mas se eles já tiverem a senha dessa pessoa, já poderão fazer login como essa pessoa e acessar a conta dessa pessoa.

Além disso, para as senhas antigas, elas podem não precisar ser armazenadas em texto estritamente simples. Eles poderiam ser armazenados de alguma maneira ofuscada. Ou armazenada como uma lista alfabética dos caracteres na senha.

Não estou dizendo que isso é uma coisa recomendada a ser feita no caso geral, mas assumindo que a tarefa que você descreveu é necessária no seu caso, essa é uma maneira de realizá-la com algumas medidas de segurança.

Kevin Fegan
fonte
Esta resposta faz várias sugestões terríveis em termos de segurança. Não devemos poder descriptografar facilmente as senhas, nem armazená-las de "alguma maneira ofuscada" em vez de criptografá-las com força.
precisa saber é o seguinte