Como Evitar Armazenamento Exposto e Vazamento de Senhas
Com o crescimento acelerado da área de tecnologia, temos observado o surgimento constante de novas empresas — muitas delas, startups. Essas empresas, em busca de inovação e agilidade no desenvolvimento, muitas vezes enfrentam o desafio de entregar soluções rapidamente com equipes pequenas e compostas por desenvolvedores juniores, com pouca experiência ou conhecimento limitado sobre segurança da informação.
Esse ritmo acelerado de desenvolvimento pode deixar vulnerabilidades expostas — algumas delas extremamente simples de resolver. Um exemplo clássico é o armazenamento incorreto de senhas no banco de dados.
O Perigo de Armazenar Senhas Expostas
Imagine que seu sistema sofra um ataque de SQL Injection, e o invasor consiga acessar toda a tabela de contas. Se as senhas estiverem armazenadas em texto puro(sem nenhum tipo de proteção), todas as credenciais estarão comprometidas de forma irreversível.
Para evitar esse tipo de problema, uma das primeiras medidas a serem tomadas é nunca armazenar senhas diretamente no banco de dados. Em vez disso, deve-se aplicar hashes criptográficos.
O que é um Hash Criptográfico?
Um hash é o resultado de uma função matemática que transforma uma entrada (por exemplo, uma senha) em uma sequência de caracteres aparentemente aleatória, com tamanho fixo. Essa transformação é unidirecional, ou seja, não é possível (ou pelo menos, não deve ser viável) reverter o hash e obter a senha original.
Um algoritmo muito utilizado para isso é o SHA-256 (Secure Hash Algorithm 256 bits).
Vamos supor que a senha seja
SENHAMUITOSEGURA
Ao aplicar o SHA-256 sobre essa senha, o algoritmo vai gerar algo como:
fe9bcb4064b6217ab43d740fc786b5db79fb1cc5a715d6ac14cdbb69fb60f322
Esse valor é o hash da senha. A principal característica desse processo é a determinística: sempre que aplicarmos SHA-256 sobre "SENHAMUITOSEGURA", o resultado será o mesmo.
Como Autenticar um Usuário com Hashes
No momento do login, o usuário informa a senha. O sistema então irá aplicar o mesmo algoritmo hash na senha digitada e comparar com o hash armazenado no banco de dados. Se os dois forem iguais, então a senha está correta — sem jamais precisar armazenar ou expor a senha original.
Hash Simples é Suficiente?
Como vimos anteriormente, hashear uma senha já impede que elas sejam expostas diretamente. Mas isso é o suficiente? Bem, não. O algoritmo apresentado, SHA-256, é muito rápido, o que o torna vulnerável a ataques de força bruta. Se a tabela for vazada, um hacker pode testar combinações de palavras várias vezes por segundo aplicando o algoritmo, até encontrar um hash que corresponda ao da senha — e, pronto, ele descobre a senha original.
O ideal é utilizar algoritmos criptográficos propositalmente lentos. Com isso, tentar adivinhar o hash por força bruta se torna uma tarefa extremamente difícil, quase impossível.
Use Algoritmos Lentos (de propósito)
A solução é utilizar algoritmos de hash propositalmente lentos, criados especificamente para armazenamento de senhas. Os mais recomendados são:
- bcrypt
- scrypt
- Argon2 (vencedor da Password Hashing Competition)
Esses algoritmos tornam ataques de força bruta extremamente demorados — e, muitas vezes, inviáveis.
E Agora, é suficiente?
Não. Os hackers utilizam-se de uma artimanha chamada Rainbow Tables.
Uma Rainbow Table nada mais é uma tabela imensa com um monte de senhas, incluindo também senhas comuns e idiotas (T3ste123, senha123, admin123, qwerty...) junto com o hash gerado a partir do respectivo algoritmo. Isto reduz imensamento o tempo necessário para quebrar uma senha, afinal é só olhar o hash na tabela e ver a senha correspondente, sem calcular o algoritmo. A solução para contra-atacar as Rainbow Tables é adicionar tempero ao nosso hash. Um salt.
O que é um Salt 🧂?
Um salt é um valor aleatório gerado de forma segura que é adicionado à senha antes da aplicação do hash. Isso garante que mesmo senhas iguais gerarão hashes totalmente diferentes.
Vamos supor que sua senha seja
SENHAMUITOSEGURA
Geramos um Salt aleatório (de preferência utilizando Secure Random)
84B03D034B409D4E
Então, concatenamos a senha com o salt:
SENHAMUITOSEGURA84B03D034B409D4E
E daí geramos o hash:
b7d5a89d89ddd16d4e66874d5b66b78622ec95b8fcc30b49779c2f4d7a2ebb7f
Agora, se um hacker tentar encontrar o hash da senha por uma rainbow table, ele não irá encontrar, pois o hash é totalmente diferente.
Mas e na hora do login?
O salt é geralmente guardado exposto, e junto com o hash gerado pela Senha + Salt da seguinte forma:
b7d5a89d89ddd16d4e66874d5b66b78622ec95b8fcc30b49779c2f4d7a2ebb7f:84B03D034B409D4E
Agora, podemos pegar a senha digitada pelo usuário e concatenar com apenas a parte do salt 84B03D034B409D4E e rodar o algoritmo neste texto concatenado. Se der o mesmo hash antes do ':', então a senha digitada está correta.
Por Fim
Há diversas outras práticas que aumentam ainda mais a segurança, como aplicar o hash em múltiplas iterações (500, 1000 ou mais), e até mesmo renovar o salt periodicamente — por exemplo, a cada login. Utilizar um algoritmo lento aliado a um salt seguro já impõe uma barreira significativa para qualquer atacante. A menos que a senha em questão seja extremamente valiosa e ofereça acesso a sistemas críticos, dificilmente valerá o esforço e o tempo necessário para quebrá-la.
Este foi meu primeiro artigo aqui na DIO, compartilhando um pouco dos meus estudos. Espero que tenham gostado e se encontrarem qualquer erro, sintam-se livre para me corrigir. :D