Introdução
No domínio da cibersegurança, a proteção das credenciais do utilizador é primordial. As palavras-passe, quando armazenadas, raramente são mantidas em texto simples. Em vez disso, são tipicamente "hashed" (transformadas através de uma função criptográfica unidirecional), o que significa que são convertidas numa string de caracteres de tamanho fixo. Isto impede que os atacantes acedam diretamente às palavras-passe, mesmo que obtenham acesso à base de dados. No entanto, um hash simples não é suficiente. Os atacantes podem utilizar tabelas pré-computadas de hashes (tabelas arco-íris) ou ataques de força bruta para descodificar palavras-passe.
É aqui que entra o "salting" (adição de sal). Salting é uma técnica onde uma string única e aleatória (o "sal") é adicionada a uma palavra-passe antes de ser "hashed". Este sal é depois armazenado juntamente com o hash. Quando um utilizador tenta fazer login, o mesmo sal é recuperado e combinado com a palavra-passe introduzida antes de ser "hashed", e o hash resultante é comparado com o hash armazenado.
Neste laboratório, irá explorar o conceito de salting de palavras-passe, compreender a sua importância no reforço da segurança e observar como uma ferramenta poderosa de descodificação de palavras-passe como o John the Ripper interage com hashes salgados. Aprenderá a identificar hashes salgados, verá como o John the Ripper os trata e compreenderá o impacto significativo que o salting tem na dificuldade de descodificar palavras-passe. Finalmente, terá uma visão sobre como o salting é implementado no armazenamento de palavras-passe no mundo real.
Compreender o Conceito de Salting
Nesta etapa, você aprenderá o conceito fundamental de salting de palavras-passe e por que ele é crucial para aumentar a segurança das palavras-passe.
Quando uma palavra-passe é "salgada" (salted), uma string única e aleatória (o sal) é adicionada à palavra-passe antes de ser "hashed". Isso significa que, mesmo que dois utilizadores tenham exatamente a mesma palavra-passe, os seus hashes armazenados serão diferentes porque um sal diferente foi usado para cada um. Isso derrota efetivamente as tabelas arco-íris pré-computadas, que dependem de um hash fixo para uma determinada palavra-passe. Também torna os ataques de força bruta mais difíceis, pois um atacante teria que computar um hash para cada palavra-passe possível e cada sal possível, em vez de apenas cada palavra-passe possível.
Vamos ver um exemplo de um hash salgado. Abra o ficheiro salted_passwords.txt que foi criado no seu diretório ~/project.
cat ~/project/salted_passwords.txt
Verá uma saída semelhante a esta:
user1:$6$salt12345$abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./:user1password
user2:5f4dcc3b5aa765d61d8327deb882cf99
user3:$6$another_salt$zyxwuvtsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA./:anotherpassword
user4:$6$short$abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./:shortpass
Note as linhas para user1, user3 e user4. Elas contêm uma secção como $6$salt12345$ ou $6$another_salt$. O $6$ indica o algoritmo de hashing utilizado (SHA-512 neste caso), e a string entre os segundos e terceiros sinais de $ (salt12345 ou another_salt) é o sal. O resto da string após o terceiro $ é o hash real da palavra-passe combinada com o sal. A linha para user2 é um hash MD5 não salgado, que usaremos para comparação mais tarde.
A principal conclusão é que cada hash salgado tem um sal único, tornando mais difícil descodificar várias palavras-passe simultaneamente usando as mesmas tabelas pré-computadas.
Identificar Hashes Salgados
Nesta etapa, você aprenderá como identificar hashes salgados com base nos seus formatos comuns. Reconhecer estes formatos é o primeiro passo para entender como abordar a descodificação ou defesa de palavras-passe.
Diferentes algoritmos de hashing e sistemas utilizam vários formatos para armazenar hashes salgados. No entanto, muitos formatos comuns, especialmente aqueles usados em sistemas Linux, seguem um padrão onde o sal é incorporado diretamente na string do hash, frequentemente delimitado por caracteres especiais como $.
Vamos reexaminar o ficheiro salted_passwords.txt e procurar especificamente por padrões que indiquem salting.
cat ~/project/salted_passwords.txt
Como observou na etapa anterior:
user1:$6$salt12345$abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./:user1passworduser3:$6$another_salt$zyxwuvtsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA./:anotherpassworduser4:$6$short$abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./:shortpass
Estas linhas mostram claramente o prefixo $6$ (indicando SHA-512 crypt) seguido pela string do sal (por exemplo, salt12345, another_salt, short), e depois o hash real. Esta estrutura é um forte indicador de um hash salgado.
Em contraste, a linha para user2:
user2:5f4dcc3b5aa765d61d8327deb882cf99
Este é um hash MD5 simples. Falta-lhe quaisquer delimitadores ou sal incorporado, tornando-o facilmente identificável como um hash não salgado.
Ser capaz de distinguir rapidamente entre hashes salgados e não salgados é crucial para profissionais de segurança e testadores de penetração, pois dita as estratégias de descodificação que podem ser empregadas.
Observar o Tratamento de Hashes Salgados pelo John the Ripper
Nesta etapa, você usará o John the Ripper, uma ferramenta popular de descodificação de palavras-passe, para observar como ele lida com hashes salgados e não salgados. Isso demonstrará as implicações práticas do salting.
Primeiro, vamos tentar descodificar as palavras-passe em salted_passwords.txt usando uma wordlist simples. Usaremos uma wordlist pequena e personalizada para esta demonstração.
Crie um ficheiro de wordlist chamado wordlist.txt no seu diretório ~/project com algumas palavras-passe comuns:
echo "password" > ~/project/wordlist.txt
echo "user1password" >> ~/project/wordlist.txt
echo "anotherpassword" >> ~/project/wordlist.txt
echo "shortpass" >> ~/project/wordlist.txt
echo "123456" >> ~/project/wordlist.txt
Agora, execute o John the Ripper contra o seu ficheiro salted_passwords.txt usando esta wordlist:
john --wordlist=~/project/wordlist.txt ~/project/salted_passwords.txt
O John the Ripper analisará os hashes. Você deverá ver uma saída indicando que ele está a tentar descodificar as palavras-passe. Ele provavelmente encontrará a palavra-passe do user2 rapidamente porque é um hash MD5 não salgado e "password" está na wordlist. Ele também encontrará as palavras-passe salgadas se os seus respetivos textos simples estiverem na wordlist.
A saída de exemplo pode parecer com isto:
Using default input encoding: UTF-8
Loaded 4 password hashes with no different salts to crack (crypt, generic crypt(3) [MD5/Blowfish/SHA1/SHA256/SHA512/XSHAa/XSHAab/bcrypt/scrypt])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
password (user2)
user1password (user1)
anotherpassword (user3)
shortpass (user4)
4g 0:00:00:00 DONE (2023-10-27 10:30) ...
Session completed.
Após o John terminar, você pode visualizar as palavras-passe descodificadas usando a opção --show:
john --show ~/project/salted_passwords.txt
Este comando exibirá quaisquer palavras-passe que o John descodificou com sucesso.
user2:password (user2)
user1:user1password (user1)
user3:anotherpassword (user3)
user4:shortpass (user4)
4 password hashes cracked, 0 left
O John the Ripper foi concebido para lidar com vários formatos de hash, incluindo aqueles com sais incorporados. Ele extrai automaticamente o sal e usa-o durante o processo de descodificação. No entanto, a presença de sais únicos para cada palavra-passe aumenta significativamente o esforço computacional necessário para a descodificação, especialmente em ataques em larga escala.
Compreender o Impacto do Salting na Descodificação
Nesta etapa, você solidificará sua compreensão de por que o salting torna a descodificação de palavras-passe significativamente mais difícil, especialmente para ataques em larga escala.
Considere a entrada user2 do nosso ficheiro salted_passwords.txt: user2:5f4dcc3b5aa765d61d8327deb882cf99. Este é um hash MD5 não salgado para a palavra-passe "password". Se um atacante obtiver uma base de dados de hashes MD5 não salgados, ele pode:
- Usar Rainbow Tables: Tabelas pré-computadas de hashes para palavras-passe comuns. Se "password" estiver na tabela, o seu hash
5f4dcc3b5aa765d61d8327deb882cf99estará lá, e o texto simples pode ser recuperado instantaneamente. - Descodificar Múltiplas Palavras-passe Simultaneamente: Se muitos utilizadores tiverem a mesma palavra-passe fraca (por exemplo, "123456"), os seus hashes não salgados serão idênticos. Um atacante só precisa de descodificar uma instância desse hash para conhecer a palavra-passe de todos os utilizadores que a partilham.
Agora, vamos olhar para os hashes salgados:
user1:$6$salt12345$abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ./:user1passworduser3:$6$another_salt$zyxwuvtsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA./:anotherpassword
Mesmo que user1 e user3 tivessem exatamente a mesma palavra-passe, os seus hashes seriam diferentes porque os seus sais (salt12345 e another_salt) são diferentes. Isto tem várias implicações críticas para os atacantes:
- Rainbow Tables são Inúteis: Como cada hash é único devido ao seu sal, as rainbow tables pré-computadas tornam-se ineficazes. Um atacante precisaria de uma rainbow table para cada sal possível, o que é computacionalmente inviável.
- Descodificação por Hash: Um atacante deve descodificar cada hash salgado individualmente. Se 100 utilizadores tiverem a mesma palavra-passe, mas cada um tiver um sal único, o atacante deve realizar 100 operações de descodificação separadas, uma para cada par hash-sal único. Isto aumenta dramaticamente o tempo e os recursos necessários para um ataque bem-sucedido.
- Dificuldade de Brute-Force: Para um ataque de brute-force, o atacante deve combinar cada palavra-passe potencial com o seu sal específico antes de fazer o hash e comparar. Isto adiciona uma camada de complexidade e retarda significativamente o processo de descodificação em comparação com hashes não salgados.
Essencialmente, o salting transforma um único problema de descodificação em muitos problemas de descodificação independentes, tornando as violações de palavras-passe em larga escala muito mais difíceis e demoradas para os atacantes.
Implementar Salting no Armazenamento de Palavras-passe
Nesta etapa, você obterá uma compreensão conceitual de como o salting é implementado em sistemas de armazenamento de palavras-passe do mundo real. Embora não construamos um sistema completo, você verá os componentes principais.
Quando um utilizador define ou altera a sua palavra-passe, um sistema seguro geralmente executa os seguintes passos:
- Gerar um Sal Aleatório: É gerado um sal aleatório criptograficamente seguro. Este sal deve ser único para cada utilizador e para cada alteração de palavra-passe.
- Combinar Palavra-passe e Sal: A palavra-passe em texto simples do utilizador é concatenada com o sal gerado.
- Fazer Hash da String Combinada: A string combinada de palavra-passe e sal é então passada através de um algoritmo de hashing forte e lento (por exemplo, bcrypt, scrypt, Argon2, ou SHA-512 crypt, como visto nos nossos exemplos). Algoritmos de hashing lentos são preferidos porque tornam os ataques de brute-force ainda mais demorados.
- Armazenar Hash e Sal: O hash resultante e o sal são armazenados juntos na base de dados. O sal não precisa de ser secreto; o seu propósito é garantir a unicidade do hash.
Quando um utilizador tenta fazer login:
- Recuperar Sal Armazenado: O sistema recupera o sal associado à conta do utilizador da base de dados.
- Combinar Palavra-passe Introduzida e Sal Armazenado: A palavra-passe introduzida pelo utilizador é combinada com o sal recuperado.
- Fazer Hash da String Combinada: Esta string combinada é então processada com hash usando o mesmo algoritmo de hashing usado durante o registo.
- Comparar Hashes: O hash recém-computado é comparado com o hash armazenado. Se corresponderem, a palavra-passe está correta.
Vamos simular a geração de um hash salgado usando o comando mkpasswd, que faz parte do pacote whois e pode gerar hashes no estilo crypt(3).
Primeiro, certifique-se de que o whois está instalado:
sudo apt install -y whois
Agora, gere um hash salgado SHA-512 para a palavra-passe "mysecretpassword" com um sal personalizado "mysalt":
mkpasswd -m sha-512 "mysecretpassword" -s "mysalt"
Você verá uma saída semelhante a esta:
$6$mysalt$some_long_hash_string_here
A saída $6$mysalt$some_long_hash_string_here é o hash salgado. $6$ indica SHA-512, mysalt é o sal que você forneceu, e o resto é o hash real. Num sistema real, o sal seria gerado aleatoriamente, não fornecido manualmente.
Isto demonstra o processo fundamental. Aplicações modernas usam bibliotecas e frameworks que abstraem esses detalhes, mas o princípio subjacente de gerar um sal único, combiná-lo com a palavra-passe, fazer o hash e armazenar ambos permanece a pedra angular do armazenamento seguro de palavras-passe.
Resumo
Neste laboratório, você obteve uma compreensão abrangente do salting de palavras-passe e do seu papel crítico no aprimoramento da segurança das palavras-passe. Você aprendeu que o salting envolve a adição de uma string única e aleatória (o sal) a uma palavra-passe antes que ela seja processada com hash, tornando cada hash único, mesmo para palavras-passe idênticas.
Você identificou com sucesso hashes salgados pelos seus formatos característicos, frequentemente incluindo delimitadores como $ e uma string de sal incorporada. Através da observação prática com o John the Ripper, você viu como esta poderosa ferramenta lida com hashes salgados e não salgados, e crucialmente, como o salting força o processo de descodificação a ser realizado numa base por hash, aumentando significativamente o esforço computacional para os atacantes.
Finalmente, você explorou a implementação conceitual do salting em sistemas de armazenamento de palavras-passe, compreendendo os passos envolvidos na geração, combinação, hashing e armazenamento de sais e palavras-passe. Este conhecimento é fundamental para qualquer pessoa envolvida em cibersegurança, seja para defender sistemas ou para compreender metodologias de ataque.
Ao tornar cada hash de palavra-passe único, o salting mitiga eficazmente a ameaça de ataques de rainbow table e retarda drasticamente as tentativas de brute-force, tornando-o uma técnica indispensável para uma segurança robusta de palavras-passe.


