Melhor maneira de armazenar a senha no banco de dados [fechado]

475

Estou trabalhando em um projeto que precisa ter autenticação (nome de usuário e senha)

Ele também se conecta a um banco de dados, então pensei em armazenar o nome de usuário e a senha lá. No entanto, não parece uma boa idéia ter senhas, apenas um campo de texto em uma tabela no banco de dados.

Estou usando c # e me conectando a um servidor expresso de 2008. Alguém pode sugerir (com o maior número de exemplos possível) qual seria a melhor maneira de armazenar esse tipo de dados?

PS Estou aberto à idéia de que essas informações não sejam armazenadas no banco de dados, se um bom motivo puder ser fornecido

Crash893
fonte
1
Faça o que fizer, se você for criptografado, não armazene a chave no código como um pôster anterior mencionado. Isso é apenas uma prática ruim.
Woody
12
'Como criar senhas, certo?' é uma questão vital. É um problema difícil e os erros têm graves consequências (lembre-se do que aconteceu com Tesco e LinkedIn). Acho que essa pergunta deve ser reaberta em programmers.stackexchange.com
Coronel Panic
2
É melhor
seguir os
5
Esta pergunta é amplamente respondida no fórum de segurança
gioele

Respostas:

405

Você está certo de que armazenar a senha em um campo de texto sem formatação é uma ideia horrível . No entanto, no que diz respeito à localização , na maioria dos casos que você encontrará (e sinceramente não consigo pensar em nenhum contra-exemplo) armazenar a representação de uma senha no banco de dados é a coisa certa a se fazer. Por representação, quero dizer que você deseja fazer o hash da senha usando um salt (que deve ser diferente para cada usuário) e um algoritmo unidirecional seguro e armazene- o , jogando fora a senha original. Então, quando você deseja verificar uma senha, faz o hash do valor (usando o mesmo algoritmo de hash e salt) e o compara ao valor do hash no banco de dados.

Portanto, embora seja bom você estar pensando sobre isso e seja uma boa pergunta, essa é realmente uma duplicata dessas perguntas (pelo menos):

Para esclarecer um pouco mais sobre a questão da salga, o perigo de simplesmente hash uma senha e armazenamento é que, se um invasor conseguir acessar seu banco de dados, ele ainda poderá usar o que é conhecido como tabelas arco-íris para poder "descriptografar" o senha (pelo menos as que aparecem na tabela arco-íris). Para contornar isso, os desenvolvedores adicionam sal às senhas que, quando feitas corretamente, tornam os ataques do arco-íris simplesmente inviáveis. Observe que um equívoco comum é simplesmente adicionar a mesma string única e longa a todas as senhas; Embora isso não seja horrível , é melhor adicionar sais exclusivos a cada senha. Leia isto para mais informações.

Paolo Bergantino
fonte
40
Eu quis dizer armazenar a senha no banco de dados em vez de armazená-la em outro lugar. Tirar essa frase do contexto faz parecer que eu estou apoiando o armazenamento de senhas simples, se você ler o resto, eu obviamente não.
Paolo Bergantino
14
Não é só isso o que eu disse, eu dirigi-lo a um grande número de mensagens que discutem sais e essa nova ...
Paolo Bergantino
1
@Paolo Bergantino: você tem certeza de que não há um erro de digitação no seu post? Ele diz "Para a maioria dos casos que você encontrará (e honestamente não consigo pensar em nenhum contra-exemplo), armazenar a senha no banco de dados é a coisa certa a se fazer". ??? Parece-contrdict seus comentários
Mitch Wheat
3
O que Paolo disse diretamente se contradiz. Um hash salgado de uma senha não é uma senha. Armazenar um hash salgado da senha no banco de dados não está armazenando a senha no banco de dados. O corpo da resposta é perfeitamente apropriado, mas sua primeira frase é extremamente enganadora.
Robert Rossney 28/06/09
40
@ Robert: Isso está ficando perigosamente perto de um jogo de semântica mesquinho, mas eu vou corrigi-lo, no entanto ...
Paolo Bergantino
54

Background Você nunca ... realmente ... precisa saber a senha do usuário. Você só deseja verificar se um usuário que conhece a senha de uma conta.

Hash It: armazene hash de senhas de usuário (criptografia unidirecional) por meio de uma forte função de hash. Uma pesquisa por "senhas de criptografia c #" fornece vários exemplos.

Consulte o criador de hash do SHA1 on - line para obter uma idéia do que uma função de hash produz (mas não use o SHA1 como uma função de hash, use algo mais forte, como o SHA256).

Agora, uma senha com hash significa que você (e os ladrões do banco de dados) não deve poder reverter esse hash de volta para a senha original.

Como usar: Mas, você diz, como uso essa senha compactada armazenada no banco de dados?

Quando o usuário faz login, ele fornece o nome de usuário e a senha (no texto original). Você apenas usa o mesmo código de hash para o hash da senha digitada para obter a versão armazenada.

Portanto, compare as duas senhas com hash (hash do banco de dados para nome de usuário e a senha digitada e com hash). Você pode saber se "o que eles digitaram" correspondeu ao que o usuário original digitou para sua senha "comparando seus hashes.

Crédito extra:

Pergunta: Se eu tivesse seu banco de dados, não poderia simplesmente pegar um cracker como John the Ripper e começar a fazer hashes até encontrar correspondências com suas senhas armazenadas com hash? (já que os usuários escolhem palavras curtas do dicionário de qualquer maneira ... deve ser fácil)

Resposta: Sim ... sim eles podem.

Portanto, você deve 'saltar' suas senhas. Veja o artigo da Wikipedia sobre sal

Consulte o exemplo C # "Como hash de dados com salt"

joej
fonte
14
Bom post, exceto por uma coisa: md5 e sha1 foram quebrados. Você provavelmente deve usar um algoritmo mais forte, como talvez a família SHA2.
Paolo Bergantino
3
Obrigado Paolo - você está correto. Como o uso do SHA2 é tão fácil quanto o MD5 e o SHA1, use o algoritmo hash mais forte.
joej
5
SHA-1 não foi quebrado. Mas para parafrasear Bruce Schneier: Ande, não corra, para o SHA-2.
30710 Ian Ian Boyd
3
"Então, você deve 'saltar' suas senhas" ... Mas o sal geralmente é armazenado no banco de dados junto com a senha, então como isso ajuda? O atacante simplesmente precisa adicionar sal às frases de ataque do dicionário contra as quais está testando. Como isso é mais seguro, além de não revelar senhas duplicadas?
trusktr
4
@joej "Você nunca ... realmente ... precisa saber a senha do usuário" - essa é uma suposição míope. Existem muitos tipos de aplicativos nos quais é realmente necessário ter uma senha armazenada de uma maneira que possa ser recuperada. Por exemplo, um aplicativo que precisa efetuar login com frequência em outro sistema com credenciais armazenadas, fornecidas e atualizadas por um usuário.
Francisco Zarabozo 21/09
29

Como um hash salgado com proteção de chave, usando um algoritmo seguro como sha-512.

nilamo
fonte
6
Na minha opinião, você sempre deve usar algoritmos lentos (como o Blowfish, por exemplo) para armazenar senhas. Este artigo é uma resposta muito melhor: security.stackexchange.com/questions/211/… . Basta colocá-lo aqui, porque esta página ainda aparece alta nos resultados da pesquisa.
Dynom
2
Seguir este conselho para o armazenamento de senhas seria uma pena terrível.
Mlissner
27

A melhor prática de segurança não é armazenar a senha (nem mesmo criptografada), mas armazenar o hash salgado (com um sal exclusivo por senha) da senha criptografada.

Dessa forma, é (praticamente) impossível recuperar uma senha de texto sem formatação.

Mitch Wheat
fonte
11
Wayne, ao salgar antes de calcular o hash, a tabela do arco-íris é derrotada efetivamente, desde que o sal seja de tamanho suficiente.
Mike Rosenblum
12
@Wayne Hartman: Não é assim. Se o valor do sal estiver exposto, você deverá gerar uma nova tabela arco-íris para esse valor específico do sal. O ponto de uma tabela do arco-íris é ter valores de hash calculados previamente. E ninguém terá uma mesa arco-íris para o seu sal específico.
22810 Ian Boyd
10

Eu recomendaria muito a leitura dos artigos O suficiente com as tabelas Rainbow: o que você precisa saber sobre esquemas de senhas seguras [link morto, cópia no arquivo da Internet ] e Como armazenar uma senha com segurança .

Muitos codificadores, inclusive eu, acham que entendem segurança e hash. Infelizmente a maioria de nós simplesmente não.

zebrabox
fonte
1
@Johan Parece que o link agora está quebrado, o que é uma pena. Aqui está uma alternativa codahale.com/how-to-safely-store-a-password
zebrabox
6

Talvez eu esteja um pouco fora do tópico, como você mencionou a necessidade de um nome de usuário e senha, e meu entendimento do problema não é o melhor, mas é algo que vale a pena considerar no OpenID?

Se você usa o OpenID, não acaba armazenando nenhuma credencial se eu entender a tecnologia corretamente e os usuários puderem usar as credenciais que já possuem, evitando a necessidade de criar uma nova identidade específica para seu aplicativo.

Pode não ser adequado se o aplicativo em questão for apenas para uso interno, embora

O RPX fornece uma maneira fácil e agradável de integrar o suporte ao OpenID em um aplicativo.

Crippledsmurf
fonte
Concordo que o openID atrapalha as pessoas, mas para esse aplicativo é um banco de dados interno de uma empresa que duvido que eles gostariam que qualquer pessoa idosa entrasse para fazer logon. Também não é necessário acesso à web para que este aplicativo funcione corretamente, portanto, eu odiaria exigir isso.
Crash893
3

No seu cenário, você pode dar uma olhada na associação ao asp.net; é uma boa prática armazenar a senha do usuário como uma seqüência de hash no banco de dados. você pode autenticar o usuário comparando a senha de entrada com hash com a armazenada no banco de dados.

Tudo foi construído para esse fim, confira a associação ao asp.net

Ray Lu
fonte
1

Gostaria MD5 / SHA1 a senha se você não precisa ser capaz de reverter o hash. Quando os usuários acessam, você pode simplesmente criptografar a senha fornecida e compará-la com o hash. As colisões de hash são quase impossíveis nesse caso, a menos que alguém obtenha acesso ao banco de dados e veja um hash para o qual já tem uma colisão.

waiwai933
fonte
2
Eu não usaria MD5 para hash - é basicamente quebrado mscs.dal.ca/~selinger/md5collision
zebrabox
3
Na verdade, não está tão quebrado. O que eles podem fazer é encontrar o mesmo valor de hash para dois arquivos diferentes. O que eles não podem fazer é reverter o MD5 e obter uma senha de trabalho.
waiwai933 28/06/09
2
Bem, isso também não seria quebrado? Você acabou de inserir a outra senha que gera o mesmo hash e está dentro. Você não precisa saber a senha original. A maneira de corrigir isso é se você saltar a senha antes do hash.
Mjarez
2
@mjuarez se você adicionar um sal com a senha antes que você use MD5 a colisão não importa, porque você não pode usar a outra senha
WiiMaxx