John the Ripper e Salting de Palavras-passe

Kali LinuxBeginner
Pratique Agora

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./:user1password
  • user3:$6$another_salt$zyxwuvtsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA./:anotherpassword
  • user4:$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:

  1. Usar Rainbow Tables: Tabelas pré-computadas de hashes para palavras-passe comuns. Se "password" estiver na tabela, o seu hash 5f4dcc3b5aa765d61d8327deb882cf99 estará lá, e o texto simples pode ser recuperado instantaneamente.
  2. 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./:user1password
  • user3:$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:

  1. 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.
  2. Combinar Palavra-passe e Sal: A palavra-passe em texto simples do utilizador é concatenada com o sal gerado.
  3. 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.
  4. 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:

  1. Recuperar Sal Armazenado: O sistema recupera o sal associado à conta do utilizador da base de dados.
  2. Combinar Palavra-passe Introduzida e Sal Armazenado: A palavra-passe introduzida pelo utilizador é combinada com o sal recuperado.
  3. Fazer Hash da String Combinada: Esta string combinada é então processada com hash usando o mesmo algoritmo de hashing usado durante o registo.
  4. 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.