2012/01/05

O Hashing e o Salting


Quando falei da vulnerabilidade de guardar passwords em formato "recuperável" numa base de dados, já estava a imaginar que algumas pessoas poderiam ficar intrigadas quando à possibilidade de conseguir validar uma password... sem que se tenha acesso a ela.


Num email que me chegou, referiam:
"Isto está incorrecto, ou seja, tem que existir no servidor uma rotina que encripta e outra que decripta senão nunca seria possível confirmar a password introduzida pelo utilizador. Desta forma quando se pede para recuperar a password, esta pode ser decriptada pela rotina do programa e enviada a password antiga ao utilizador. "

O problema de se guardar uma password de um utilizador numa base de dados, usando encriptação, é que a mesma pode ser revertida de forma a dar a password original. (E torna-se lógico assumir que um atacante que tenha acesso à base de dados de um site, tenha igualmente acesso aos ficheiros e scripts que fazem essa mesma encriptação e desencriptação.)


Precisamos portanto... de algo ligeiramente diferente...


Bem vindo ao mundo das Hashes


Os algoritmos de hashing permitem transformar uma sequência de dados num resultado aparentemente aleatório, e que - mais importante para o nosso caso - não pode ser feito de forma inversa. Ou seja... depois de aplicarem este processo a um pedaço de texto... puff... nunca mais poderão saber o que lhe deu origem.

As suas aplicações são muitas: poderão já ter ouvido falar do MD5 ou SHA-1/2, ou de ferramentas de validação da integridade de ficheiros que as utilizam. Usando o resultado MD5 de um ficheiro, torna-se possível verificar se o mesmo não foi alterado... mesmo que um único bit se tenha corrompido no meio de alguns Gigabytes de dados.


E para que nos serve isto, se não podemos saber a password original a partir do resultado "hashado"? A questão é que... não precisamos dela! Quem a sabe é o utilizador que a introduziu pela primeira vez. E que, ao introduzi-la novamente, irá dar o mesmo resultado, batendo certo com o valor "hashado" que temos guardado na nossa base de dados. Valor esse que, mesmo que seja descoberto por um hacker, não lhe permitirá saber a password original do utilizador.


Por exemplo, utilizando o MD5 (que já não é recomendável para este efeito, por ter ele próprio falhas de segurança)

A palavra "password", sujeita ao hashing dá por resultado: 5f4dcc3b5aa765d61d8327deb882cf99

Bem podem divertir-se a tentar encontrar uma qualquer outra palavra que dê este mesmo resultado. Elas existem, mas a probabilidade de as descobrirem são infinitesimais. Quando o utilizador regressar ao site e introduzir a password, precisamos apenas aplicar o mesmo sistema e ver se o resultado final bate certo, e assim podendo testar se a password é válida sem necessidade de a saber.


As Vulnerabilidades

Mas, há gente inteligente que se diverte a tentar quebrar estas coisa, e como tal, depressa surgiram técnicas de ataque a estas coisas. Se é impossível "andar para trás" e descobrir a palavra que deu origem a uma hash, podemos então criar listas de hashes de passwords e palavras comuns, e ver se alguma delas coincide com o que pretendemos.

Assim torna-se necessário um passo adicional, conhecido por "salting". Este salting nada mais é que adicionar à password um outro elemento qualquer, que garanta alguma variedade à palavra antes de ser "hashada".

Por exemplo, em vez de aplicar o sistema à palavra "password", poderíamos adicionar-lhe a frase "só para complicar" no final. Isso iria dar um resultado completamente diferente, tornando irrelevante a procura pelo resultado MD5 da palavra "password" simples.

Esse "salt" tanto pode ser uma palavra estática para todos os utilizadores, como diferente para cada uma deles, sendo apenas necessário que seja algo que possa ser acedido pelo sistema. Por exemplo, o nome do utilizador, ou email, ou data de registo inicial, ou uma combinação de algumas, ou todas elas - há infinitas possibilidades.

Assim, o recurso a bases de dados de hashes conhecidas torna-se irrelevante.


Com isto espero ter ajudado um pouco a que percebam como é possível guardar e validar passwords sem necessidade de guardar as passwords, e tornando praticamente impossível que um atacante as consiga recuperar caso tenha acesso à base de dados onde estão guardados os dados dos utilizadores.

11 comentários:

  1. Por acaso tive a ler algo semelhante hoje aqui: http://dankaminsky.com/

    E irrita-me profundamente receber a minha password no email quando me registo num site ou quando faço recuperação das mesma...

    ResponderEliminar
  2. Para além de que guardar passwords na base de dados apenas encritadas sem salt, facilmente se faz um dicionário de MD5 por exemplo. Alias quem ainda usa MD5 como unico recurso para guardar passwords vive literalmente no seculo passado.

    Anyways, já uso este sistema há algum tempo. Em principio usava apenas uma palavra para gerar o salt, mas agora até uso informação do user para o fazer. Penso que seja a melhor forma.

    ResponderEliminar
  3. Do mesmo modo que o uso de uma função de encriptação/desencriptação é sujeita a hacking (alguém que entenda como funcione a script, ou que a consiga obter), o uso de Salt leva à mesma questão. Depois de saber como o Salt é calculado, voltamos a ter uma simples hash.

    ResponderEliminar
  4. @Alberto

    Uma "simples" hash que não consegues reverter facilmente, entenda-se.
    Tens que refazer um dicionário de hashes com base em passwords conhecidas, ou recorrer a bruteforce... e que no caso de uma password segura, demorará tempos infinitos.

    São tudo métodos de "complicação" adicional para dar mais segurança a passwords que à partida não sejam das mais seguras.

    ResponderEliminar
  5. Miguel Roxo5/1/12 19:44

    Com todo o respeito, já que estamos com preciosismos e tendo ouvido eu várias vezes ao longo dos últimos 2 anos "sermões" da parte de os meus professores de cadeira de segurança aqui fica:

    http://blogs.fullsix.pt/2009/03/04/cifrar-vs-encriptar/

    ResponderEliminar
  6. @Miguel

    Estou consciente disso... Mas foi mesmo por opção pessoal que usei o "encriptar"... talvez para que ninguém se baralhasse a ler o artigo à pressa e ainda apanhar um "chifrar" lá pelo meio - o que com a minha tendência para deslizamento dos dedos no teclado, seria altamente provável de acontecer mesmo! :))

    ResponderEliminar
  7. Este comentário foi removido pelo autor.

    ResponderEliminar
  8. @Miguel Roxo.

    Muito útil e bem sintetizada a explicação das diferenças entre cifra e encriptar.

    Em contexto de segurança informática começarei a usar preferencialmente a palavra cifra.
    Bem-haja

    ResponderEliminar
  9. Prefiro encriptar. Comunicar significa passar a mensagem. O Carlos optou bem.
    Link, site, muito melhor que dizer hiperligação e sítio.
    Sou daquelas pessoas que passa a vida a chatear os contactos do messenger sempre que corrigem os seus erros de teclanço tipo "chaguei às 15h....*cheguei". Eu percebi!

    Sobre o assunto, pergunto eu, se uma password está protegida com md5 e senão conseguimos andar na direção contrária, só sobra testar listas de passwords.
    Qual seria a probabilidade de sucesso de um ataque de força bruta nos dias que correm? Os servidores não estão programadas para bloquear + do que X tentativas e coisas do género?

    ResponderEliminar
  10. @Mori

    O caso do MD5 é especial pois sofre de vulnerabilidades (e o SHA-1 também) que facilitam as tentativas de crackanço da coisa.

    Claro que é impossível garantir que se tenha a password correcta (imagina que tinhas usado como password os Lusíadas completos!), mas à partida será possível obter uma palavra original que te produza aquela "hash", e que servirá como password real.


    Mas sim... claro que há muitos outros impedimentos pelo meio numa situação real. Desde o "salt", à limitação de número de tentativas, num site, ou até ao simples factor "tempo".

    Por norma os ataques de que se falam ocorrem após um atacante ter tido acesso a uma BD (base de dados) com as hashes dos utilizadores, e aí podendo aplicar todo o hardware que possuir (CPUs, GPUs, cloud, etc.) nessa tarefa sem esse tipo de constrangimentos. Não tendo acesso à BD, então nem sequer se coloca essa questão - e é isso que sucede na maioria dos casos, felizmente! :)

    ResponderEliminar
  11. Tudo correcto no artigo, apenas faço um reparo, a utilização abusiva do termo "encriptar" e derivados.
    Tive um professor na faculdade de segurança que chumbava quem usasse estes termos, e insistia que os termos correctos são cifrar, decifrar, cifra, decifração, etc...
    Alguém explica isto com mais detalhe aqui: http://tiagonmas.blogspot.pt/2012/03/cifrar-vs-encriptar-eis-questao.html

    ResponderEliminar