Checkmate — TryHackMe Writeup
Room Overview
Checkmate is a password-focused TryHackMe room built around a single idea: humans are bad at picking passwords, and that badness compounds. A fictional admin, Marco, has deployed several internal services on the same host — an admin panel, an employee/social platform, and a personal account with SSH access behind it. Each stage leaks something (a password, a birthdate, a habit) that makes the next stage crackable. Nothing in the room requires a software exploit; it’s entirely about weak, reused, and predictable credentials.
Target: 10.49.179.252, with services on ports 5001, 5002, 5003, and SSH.
Stage 1 — Default Credentials (Port 5001)
The first login form (/login, POST body of username + password, failure string Invalid credentials.) looked like an unconfigured admin panel, so instead of guessing I went straight for a known default-credentials list:
hydra -l admin -P /usr/share/wordlists/seclists/Passwords/Default-Credentials/default-passwords.txt \
-f -V -s 5001 10.49.179.252 http-post-form \
'/login:username=^USER^&password=^PASS^:Invalid credentials.'-l admin— assumed/given username-P— SecLists' default-passwords list-f— stop as soon as a valid pair is found-V— verbose, to confirm the failure string was matching correctly
Result:
[5001][http-post-form] host: 10.49.179.252 login: admin password: 12345Admin access, on a device that was never reconfigured past its factory defaults. Default credential lists are always worth trying first against an exposed login form before anything more elaborate.
Stage 2 — OSINT Wordlist with CeWL (Port 5002)
The second panel wasn’t going to fall to a generic list — this one needed vocabulary specific to the organization. Rather than guessing at company-flavored words, I let CeWL crawl the site and build a wordlist from whatever language actually appeared on the pages:
cewl -d 2 -m 6 --lowercase -w keywords.txt http://10.49.179.252:5002/-d 2— crawl two links deep-m 6— discard anything under 6 characters--lowercase— normalize casing
This produced a tight, relevant list of job-posting and company-culture terms:
security, careers, excellence, engineering, innovation, digital,
employee, future, remote, engineer, tooling, response, design,
intern, search, talent, transformation, portal, designer, berlin,
centered, workshops, support, product, specialist, reliability,
automation, operations, endpoint, process, feature, disabled,
internal, access, profiles, username, password, features, enabled,
locations, benefits, candidate, opportunity, senior, featured,
analyst, threat, detection, culture, infrastructure, london,
projects, operational, internship, hybrid, incident, development,
mindset, devops, platform, pipelines~60 words, all pulled straight from the target instead of a bloated generic list. Fed into Hydra against marco:
hydra -l marco -P keywords.txt -f -V -s 5002 10.49.179.252 http-post-form \
'/login:username=^USER^&password=^PASS^:Invalid credentials.'Result (hit on attempt 3 of 61):
[5002][http-post-form] host: 10.49.179.252 login: marco password: excellenceA raw keyword scraped from the site’s own content, no transformation applied. Lesson: a scraped, context-aware wordlist beats a huge generic one almost every time.
Stage 3 — Personalized Password Cracking (Port 5003)
Logging into Marco’s account on port 5002 leaked personal information that made a much stronger-looking password on port 5003 crackable:
Field Value First Name Marco Surname Bianchi Nickname marky Birthdate (DDMMYYYY) 14021995
Get Neelesh Pandey’s stories in your inbox
Join Medium for free to get updates from this writer.
Marco had also posted a “password tip” on his social profile revealing his personal methodology:
Take a company keyword, capitalize it, append the year (or any other number), and add an exclamation mark.
That single post ends up being the key to Stage 5 as well — but for Stage 3, the more immediate lead was his name and birthdate. I built a candidate list (marco.txt) combining name/surname/nickname variants with permutations of 14021995, in the spirit of what a tool like CUPP generates automatically:
hydra -l marco -P marco.txt -f -V -t4 -s 5003 10.49.179.252 http-post-form \
"/login:username=^USER^&password=^PASS^:Invalid credentials."-t4— throttled to 4 tasks since this was a larger list (2,816 candidates) and I wanted a stable run
Hydra worked through name/date permutations — Bianchi2495, Bianchi2018, Bianchi024, and dozens more — before landing on:
[5003][http-post-form] host: 10.49.179.252 login: marco password: Bianchi2495Surname plus a scrambled fragment of his birth year. Exactly the “personal but not obvious” pattern that OSINT-driven wordlists are built to catch.
Stage 4 — Recovering a Filename from Its Hash (Port 5003)
Challenge: Marco recently uploaded a new profile picture. The platform renames uploads to the SHA-256 hash of the original filename, saved as (hash).png. Task: recover the original filename.
After logging in with the Stage 3 credentials, I opened View Page Source on Marco’s profile and found the image reference:
d34a569ab7aaa54dacd715ae64953455d86b768846cd0085ef4e9e7471489b7b.pngThat string is a hash of a filename, not the filename itself — but since it’s almost certainly a hash of a short, guessable string rather than a high-entropy secret, it’s crackable the same way a leaked password hash would be. Instead of running a local wordlist attack, I checked it against CrackStation, which maintains large precomputed tables for exactly this kind of common-input hash:
d34a569ab7aaa54dacd715ae64953455d86b768846cd0085ef4e9e7471489b7b
→ familyMarco’s profile picture had originally been uploaded as family (family.png) before the platform hashed the filename on upload — a small personal detail consistent with the human-centered OSINT theme running through the room.
Stage 5 — Pattern-Based SSH Brute Force
The final piece uses the one clue that’s been sitting in plain sight since Stage 3: Marco’s own “password tip” post.
Take a company keyword, capitalize it, append the year (or any other number), and add an exclamation mark.
That’s a full password-generation rule, not just a hint — capitalized keyword + 2-digit (or 4-digit) year-style number + !. Combined with the company keywords already scraped in Stage 2 (security, excellence, innovation, digital, and any others gathered from the site, e.g. cloud), this narrows SSH's keyspace enormously compared to blind brute-forcing.
Building the pattern-based wordlist with Crunch — one command:
Rather than running Crunch five separate times, one per keyword, a small shell loop generates the whole list in a single command:
rm -f passlist.txt; for w in Security Excellence Innovation Digital Cloud; do \
len=$((${#w}+5)); crunch $len $len 0123456789! -t "${w}20%%!" >> passlist.txt; donefor w in Security Excellence Innovation Digital Cloud; do ... done— loops over all five scraped keywordslen=$((${#w}+5))— computes the total password length on the fly: the keyword itself, plus20(2 chars),%%(2 digit placeholders), and!(1 char) — sominandmaxnever have to be typed by hand per wordcrunch $len $len 0123456789! -t "${w}20%%!"— same template logic as before (%= digit placeholder, everything else literal), just parameterized on$w>> passlist.txt— every iteration appends to the same file, so it ends up containing all five keyword patterns combined- The leading
rm -f passlist.txtjust makes sure old runs don't get appended on top of a stale file
Same output as running Crunch five times by hand, in one line.
This produces every Keyword20XX!-style candidate for each keyword pulled from the site — a few thousand tightly-scoped guesses instead of millions of blind ones.
Running it against SSH:
hydra -l marco -P passlist.txt -f -V -t4 10.49.179.252 ssh-t4— kept the task count modest since SSH brute-forcing is heavier per-attempt than an HTTP form, and some SSH daemons rate-limit or drop connections under high concurrency
Hydra worked through the Keyword20XX! candidates and, after a while, landed on a valid SSH credential:
[ssh] host: 10.49.179.252 login: marco password: Security2024!Security2024! — the capitalized keyword, the current-feeling year, and the exclamation mark, exactly as Marco described in his own post. That's SSH access, and the final stage of the room.
Writeup for the TryHackMe “Checkmate” room.







