• Nenhum resultado encontrado

Vazamentos e segurança no armazenamento de senhas

N/A
N/A
Protected

Academic year: 2019

Share "Vazamentos e segurança no armazenamento de senhas"

Copied!
11
0
0

Texto

(1)

23/02/2014 por Gustavo Cardial Leave a reply »

Vazamentos e segurança no

armazenamento de senhas

Postado originalmente em 27/06/2012

*** Aconteceu há umas semanas. Você provavelmente ouviu falar:

Vazamentos como esse são mais comuns do que parecem, e em sites de todos os portes. Aliás, além do LinkedIn, os usuários dos sites Last.fm e eHarmony também tiveram suas senhas expostas recentemente. A primeira coisa a se evitar, é claro, são os acessos não autorizados a um banco de dados. Mas uma vez que a invasão aconteça, estará tudo perdido? Em outras palavras, quando ocorre o vazamento duma base de dados, será inevitável que as senhas ali armazenadas sejam utilizadas por terceiros?

Felizmente, a resposta é não.

Tudo depende de implementarmos um armazenamento seguro de senhas. Este post é sobre isso.

Texto puro

Sempre acontece: você esquece a senha daquele site e preenche o formulário de esqueci minha senha. Depois disso, geralmente, você recebe um link por e-mail, que te permite criar uma nova senha.

Ao invés disso, no entanto, alguns sites preferem te enviar um e-mail com a senha exata que você escolheu. Péssimo sinal.

(2)

Assim, caso as bases de dados destes sites sejam comprometidas, os hackers de plantão terão uma bela lista de usuários e senhas.

Aí, quem usar a mesma senha para e-mail, redes sociais e outros sites… se deu mal.

Funções hash

As funções hash mapeiam uma entrada de tamanho variável (domínio) numa saída de tamanho fixo (imagem):

onde H é a função hash, Z2 é {0, 1} (binário), m é o tamanho da entrada e n é o tamanho da saída (ambos em número de bits).

Complicou? Talvez essa imagem simplifique:

Ou seja…

Essas funções transformam uma entrada de tamanho qualquer numa saída de tamanho fixo. A essa saída, damos o nome de hash. No diagrama acima, a entrada FOX gerou o hash DFCD3454.

Uma característica importante: as funções hash são o que chamamos de one way functions. Isso significa que podemos transformar uma entrada num hash, mas não o contrário: com o hash em mãos, é impossível calcular a entrada que o gerou.

Existem várias funções hash. Cada uma delas possui um algoritmo diferente, que dita as operações que serão feitas com a entrada, a fim de gerar o código de saída. Duas funções muito famosas são a MD5 e a SHA-1. O hash MD5 da string “gustavo”, por exemplo, é 4c96f8324e3ba54a99e78249b95daa30. Já o hash da

(3)

site md5 Hash Generator.

As funções hash têm várias utilidades, mas aqui só citarei uma.

Apesar de não terem sido criadas exatamente para isso, os desenvolvedores perceberam que poderiam usar essas funções para armazenar, com segurança, as senhas de seus usuários. Dessa forma, ao invés de armazenar uma senha em texto puro, ela é antes passada a uma função hash.

O hash resultante é, então, armazenado no banco de dados.

Daí, quando um usuário tenta realizar login, o sistema gera o hash da senha fornecida, que é comparado com o hash que está no banco de dados. Se forem iguais: login efetuado com sucesso!

A segurança deste mecanismo advém do fato de que para autenticar seus usuários o sistema não precisa, em momento algum, armazenar as senhas propriamente ditas. Somente seus hashs.

Assim, na triste eventualidade do banco de dados ser comprometido, tudo o que o atacante terá em mãos são os hashs. E você deve se lembrar que as funções hash são one way functions, como dito acima. Portanto, as senhas dos usuários estarão seguras.

Quer dizer… Isso já foi verdade, mas só até meados dos anos 70.

Atacando hashs

Todo profissional de tecnologia deve conhecer a famosa Lei de Moore. Não, não é Murphy, é Moore mesmo. Esse cara era presidente da Intel, e em 65 ele fez uma previsão que, por ter se mostrado bastante próxima da realidade, conquistou o status de lei: a cada dois anos, o número de transistores que pode ser colocado num circuito integrado tende a dobrar.

A consequência direta da Lei de Moore é que o poder de processamento dos computadores aumentava rapidamente.

Então. Percebendo que contavam com máquinas cada vez mais velozes, os crackers notaram que era cada vez mais fácil descobrir as strings originais de um hash.

Para isso, bastava criar um programinha simples que gerasse os hashs de várias strings – aleatoriamente, sequencialmente ou através dum arquivo com palavras comuns. Por fim, era só comparar os hashs gerados com os hashs a serem crackeados, até chegar a uma igualdade.

Complicou, né? Um exemplo.

Invadem um site onde eu estou cadastrado, e em seu banco de dados consta que o hash da minha senha é 4c96f8324e3ba54a99e78249b95daa30 (“gustavo”, em MD5).

O invasor, então, cria um programinha que gera os hashs de várias strings sequenciais: primeiro gera o hash de “A”. Depois de “B”, depois de “C”, “D”, …, até “Z”. E então de “AB, AC, AD, …”, e assim por diante. Num loop, até chegar em “ZZZZZZZ”.

Eventualmente, o programa chegará à string “gustavo”, e verificará que o hash dessa string é idêntico ao hash que está no banco de dados. Pronto, minha senha foi descoberta.

(4)

Se isso já não bastasse, ninguém mais precisa criar seus próprios programas para quebrar hashs.

Existem diversos softwares disponíveis para download que realizam a tarefa com maestria, sendo altamente otimizados. Não só testam senhas de “AAAAAA” a “ZZZZZ”, como também usam listas de palavras (wordlists, ou arquivos de dicionário), combinações entre elas e diversos outros algoritmos que geram senhas prováveis. Um desses softwares que quebra hashs, provavelmente o mais famoso, é o John The Ripper(“Jack, o Estripador” em português). Ele está disponível para download aqui: John the Ripper password cracker.

A quantidade de desenvolvedores web que, ao armazenar senhas como hashs, pensam “nossa, meu sistema é tão seguro!” é enorme. Mas agora você sabe que eles estão errados.

O LinkedIn, diga-se de passagem, cometeu o mesmo erro.

(5)

Com ela, é possível crackear testar a segurança das senhas armazenadas numa base de dados. A lista inclui todas as palavras contidas na Wikipedia (em 2010), em vários livros do Project Gutenberg, dicionários e diversos vazamentos de senhas que ocorreram até a data desta atualização.

Lookup tables

Em computação, frequentemente nos deparamos com uma situação chamada space-timetradeoff. É quando um algoritmo consegue reduzir seu tempo de processamento mediante a utilização de mais memória; ou vice-versa. Em outras palavras, uma situação onde é possíveltrocar memória por processamento (espaço por tempo).

Com o tempo, os crackers perceberam que quebrar hashs era uma dessas situações.

Primeiro, pegaram um software como o que eu mostrei acima (que gera milhares de hashs por segundo) e o modificaram um pouco. Ao invés de gerar os hashs e compará-los em tempo real a um hash alvo, esses hashs são gerados e armazenados numa lista, juntamente com as entradas que os geraram.

Com isso, obtém-se uma espécie de dicionário de hashs, onde é possível consultar tanto o hash, quanto a entrada que o gerou. Esses dicionários são chamados de lookup tables.

Em posse de gigantescas lookup tables (que ocupam muita memória), antes de aplicar a técnica de brute force abordada acima, é aplicado um dictionary attack: os softwares dos crackers comparam o hash a ser quebrado com todos os hashs da lookup table.

Computacionalmente, comparar um hash alvo com cada hash da lookup table é muito menos custoso do que gerar, em tempo real, cada um daqueles hashs e então fazer a comparação: a economia de processamento será grande, sendo possível crackear o hash num tempo muito menor do que seria necessário só com brute force. Por fim, caso o hash a ser quebrado não conste na lista, aí sim pode-se começar a realizar o processo de brute force, dessa vez com senhas mais elaboradas, que não constem na lookup table.

(6)

As lookup tables são de grande ajuda aos crackers. Elas permitem, por exemplo, que hashs sejam quebrados em massa. Como assim? Digamos que você invadiu um site que tinha milhões de usuários cadastrados, e copiou seu banco de dados. Digamos também que as senhas desses usuários estão armazenadas neste banco como hashs MD5.

São muitos hashs para crackear, não? Felizmente, você tem uma ótima lookup table, de vários gigabytes de tamanho. Um jeito ótimo de começar, então, é cruzar as duas listas: hashs a crackear e hashs da lookup table. Assim, logo de cara você terá a lista de usuários cujas senhas se encontram na sua tabela.

Depois disso, é só partir pro brute force contra os demais hashs da lista.

O contra-ataque

Como você deve perceber, se leu até aqui, a coisa tá feia pra quem precisa proteger as senhas num banco de dados.

A ideia de utilizar hashs, na teoria, parecia muito promissora. Mas, como vimos, o alto poder de processamento dos computadores modernos torna essa proteção praticamente nula.

Para piorar a situação, as lookup tables tornam a quebra de hashs ainda mais trivial, permitindo aos crackers economizar muito processamento computacional, e consequentemente descobrir senhas muito mais

rapidamente.

Porém, nada temam. O duelo contra os crackers de senhas não acabou, e ainda está prestes a sofrer uma reviravolta.

Salts

O primeiro passo para mitigar ataques às hashs é a adoção do que chamamos de salt.

(7)

O exemplo acima representa o processo de cadastro duma senha num banco de dados. Inicialmente, temos a senha “hello”. Então, o salt “3ab9″ é gerado aleatoriamente, e então concatenado com a senha, resultando na string “hello3ab9″. Essa string, por sua vez, serve como entrada a uma função hash (tipo MD5), que gera o hash “39e19b234…”. Finalmente, este hash armazenado no banco de dados, e junto com o salt. Ufa.

Quando um usuário tentar fazer login, a senha por ele informada será concatenada ao seu respectivo salt (que estará no banco de dados). É gerado o hash dessa string resultante, que é comparado ao hash que está no banco. Se forem iguais, login efetuado com sucesso.

(8)

Já nos livramos das lookup tables. Agora vamos ao golpe final.

Key stretching

A adoção de salts impede que as lookup tables funcionem. No entanto, caso um banco de dados vaze, o hash e seu salt serão expostos. E isso é suficiente para que ataques brute force ainda funcionem.

Ora, para realizar um ataque desses, basta que um software gere hashs para várias senhas aleatórias, como de costume, mas que antes essas senhas sejam concatenadas sempre com o mesmo salt, que é conhecido. Afinal, como mitigar ataques brute force?

Vimos que tais ataques são possíveis pois, em função do crescente poder computacional, é possível gerar milhares de hashs por segundo. Isso porque os algoritmos de hashs, como MD5 e SHA-1, foram originalmente criados para aplicações que precisavam de certa velocidade. Logo, hashs são de rápido cálculo.

A solução óbvia, portanto: tornar o cálculo de hashs mais demorado.

Aí que surgiu o termo key stretching. Essa técnica consiste justamente em gerar os hashs através de algoritmos que demandem intenso processamento computacional. Como as funções hashs são velozes,

e velocidade é nossa inimiga, foram inventados diversos algoritmos para tornar o processo de geração de hashs demoradas. Tecnicamente, esses algoritmos são chamados depassword hashing schemes.

A ideia geral desses algoritmos é simples: pegar a senha, concatenar com um salt aleatório e então gerar hashs, de forma iterativa, um grande número de vezes.

Um exemplo.

(9)

“f8375hf743hf734″ (não é o hash correto, é só um exemplo pra ficar mais curto).

Ok, então este hash é novamente enviado à mesma função hash, que gera um novo hash (o hash do hash), digamos “27h3d723dh2″. O novo hash é passado à função hash denovo, e obtemos um novo hash. E assim sucessivamente, digamos umas 100 vezes.

A ideia é que, no total, as iterações levem cerca de 1 segundo. Desta forma, se para calcular o hash final de uma string for necessário 1 segundo, para calcular os hashs finais de milhares de strings serão

necessárias várias horas, e não alguns segundos, como antes. Pronto, o brute force se torna inviável.

E nunca podemos, é claro, nos esquecer da Lei de Moore. A ideia é que à medida que o poder computacional aumente e um algoritmo que demorava 1 segundo comece a demorar menos, onúmero de iterações seja aumentado para manter este tempo.

Ah, e o algoritmo realmente não deve demorar mais de 1 segundo. Pois todo esse processo terá de ser aplicado também a cada tentativa de login, a fim de verificar se as senhas dos usuários estão corretas. E ninguém quer esperar muito tempo pra fazer login num site, né?

Enfim. Vale mencionar que entre as iterações desses algoritmos, geralmente, são realizadas certas operações adicionais para realmente garantir a “aleatoriedade” do hash e dificultar outras formas de ataque. Mas a ideia básica dos password hashing schemes é essa.

Segue o diagrama de um desses algoritmos, o MD5-Crypt. É mais para ilustrar, pois hoje em dia até ele é considerado fraco. Ou seja, tem sido crackeado em tempo hábil.

(10)

Bcrypt

Aos que quiserem usar um password hashing scheme seguro em sua aplicação web, recomendo o Bcrypt. No Google é possível encontrá-lo implementado em diversas linguagens. Recomendoesta implementação aqui, em PHP; ou esta aqui, em Java.

Outras medidas

Usando o devido password hashing scheme, você pode se considerar seguro.

(11)

1) Política de senhas

É sempre bom implementar uma boa política de senhas. Impedir que seus usuários utilizem senhas imbecis, como “senha” ou “1234″, e tal.

Com técnicas como brute force, forçar o usuário a usar vários tipos de caracteres, como números, pontos e misturar maiúsculas e minúsculas não é assim tão efetivo. Prefira forçá-lo a escolhersenhas longas. E nada de palavras comuns, que constem no dicionário, ou jogos com palavras. Muitas das senhas crackeadas do

LinkedIn eram assim.

2) Esconder o salt

Referências

Documentos relacionados

apela para a realização de iniciativas que promovam informação integrada aos viajantes e bilhética intermodal; solicita a aplicação de medidas que visem melhorar a qualidade

A combinação dessas dimensões resulta em quatro classes de abordagem comunicativa, que podem ser exemplificadas da seguinte forma: interativo/dialógico: professor e

Como nos caso de descarga atmosférica os valores de corrente são muito elevados, mesmo se a malha de aterramento tem um baixo valor de resistência, as tensões de passo e toque

“ Esta taxa, além de refletir a liquidez dos recursos financeiros no mercado monetário, tem a característica de juros remuneratórios ao investidor.

A pesquisa foi realizada com os educadores e gestores de escolas municipais e estaduais da cidade de Vilhena-RO, tendo como objetivo compreender a importância

 Direito recebe informações de outros subsistemas sociais  Processa segundo a sua linguagem interna..  Envia informações para os

Preliminarmente, alega inépcia da inicial, vez que o requerente deixou de apresentar os requisitos essenciais da ação popular (ilegalidade e dano ao patrimônio público). No

Os objetivos deste estudo foram: (1) avaliar a qualidade de vida em pacientes com hipertensão arterial sistêmica por meio de um questionário, que visa a transformar