Welcome to another Hack the Box exercise. In this blog post, I will show you how I owned the Planning machine on Hack the Box. Hack The Box is a cybersecurity platform that helps you bridge knowledge gaps and prepares you for cyber security jobs. You can also test and grow your penetration testing skills, from gathering information to reporting. If you are new to this blog, please do not forget to like, comment, and subscribe to my YouTube channel and also follow me on LinkedIn for more updates.
About the Machine
Planning is an easy Linux machine on HackTheBox that demonstrates a well-paced attack chain involving reconnaissance, password reuse, enumeration of internal services, and Docker exploitation. The box is themed around a fictional project management environment where users manage infrastructure using tools like Grafana and Docker containers.
Once on the box as a low-privileged user, we analyze cron jobs and discover a Docker container being regularly backed up. The backup process includes a ZIP archive encrypted with a hardcoded password, which can be extracted and inspected to retrieve sensitive information. Internal services such as MySQL and a local service on port 8000 are only accessible via SSH tunneling, which is essential to pivot deeper into the host.
The machine concludes with the enumeration of internal Docker services and privilege escalation via Docker misuse or cron job manipulation, ultimately leading to root access.
The first step in owing the Planning machine like I have always done in my previous writeups is to connect my Kali Linux terminal with Hack the Box server. To establish this connection, I ran the following command in the terminal:
This established a secure tunnel (tun0) to the HTB network using AES-128-CBC encryption and SHA256 authentication. Once the initialization was complete, I could start enumerating and attacking the target machine from inside the HTB network.
Once the connection was successful, I started the target machine and I was assigned an IP address 10.10.11.68. Under the machine information, two credentials which are likely to be a username and password were given as: admin & 0D5oT70Fq13EvB5r. Next, I started with an aggressive Nmap scan to identify open ports and services::
The scan revealed two open ports:
- Port 22 running OpenSSH (not immediately useful).
- Port 80 running Nginx hosting a website titled "Edukate - Online Education Website".
Additionally, the reverse DNS entry grafana.planning.htb hinted at the presence of a Grafana instance, which I noted for further exploration. Based on these findings, I added grafana.planning.htb to my /etc/hosts and began manual web enumeration.
To uncover hidden subdomains or virtual hosts, I used ffuf to fuzz the Host header:
This technique filters out generic 178-byte responses and attempts to discover valid vhosts. It revealed:
This indicated the presence of a Grafana instance, likely accessible via http://grafana.planning.htb/. I added it to my /etc/hosts file to access it in the browser (I have previously done this manually using sudo nano /etc/hosts but you can add it by running the following command in your terminal):
Afterwards, I launched my browser and visited http://grafana.planning.htb. This displayed a webpage with a username and password text input field. Using the credentials from the machine information from Hack the Box, I was able to sign into the website.
At the bottom of the webpage, my eye caught something that looks like a hint on how to own the machine. The website was built using Grafana v11.0.0, Grafana is a multi-platform open source analytics and interactive visualization web application. It can produce charts, graphs, and alerts for the web when connected to supported data sources. Next, I searched for vulnerabilities associated with the version 11.0.0 and stumbled upon CVE-2024-9264-RCE-Exploit in Grafana via SQL Expressions. After signing in, I browse through the dashboard but didn't find anything really useful there.
Then I read the proof of concept to better understand what the CVE is and how to leverage it. The repository contains a Python script that exploits a Remote Code Execution (RCE) vulnerability in Grafana's SQL Expressions feature. By leveraging insufficient input sanitization, this exploit allows an attacker to execute arbitrary shell commands on the server. This is made possible through the shellfs community extension, which can be installed and loaded by an attacker to facilitate command execution.
I cloned the repository using the following command and navigated right into it:
Before running the exploit, I checked my IP address and start the netcat listener at port 6666 to listening to incoming connection:
I used a known exploit against Grafana v11, which allowed RCE via [CVE-2024-9264-RCE-Exploit in Grafana via SQL Expressions]. I used the following PoC:
Once the reverse shell connected, I was dropped into a non-interactive shell (
sh: 0: can't access tty
). Navigating around, I found myself in /usr/share/grafana
, indicating that the shell is running inside the Grafana container or environment.By inspecting environment variables, I discovered admin credentials:
- Username:
enzo
- Password:
RioTecRANDEntANT!
This could be useful for accessing Grafana’s web interface or reusing the credentials for lateral movement.
Key directories like /etc/grafana/provisioning
and /var/lib/grafana
were explored to find sensitive configs or databases.
With the credentials retrieved from Grafana’s environment variables (enzo:RioTecRANDEntANT!), I attempted SSH login into the target machine:
This granted me a stable, interactive shell on the host running Ubuntu 24.04.2 LTS. Inside the home directory of
enzo
, I found the user.txt
file and successfully captured the flag:Hurray!!! I got my user flag.
After securing the user flag as enzo, I then began local enumeration to search for paths to escalate privileges to root. Notably, I discovered a custom cron configuration file at:
This revealed two scheduled tasks:
- A daily backup job that archives a Docker image named root_grafana, compresses it, and zips it using the password P4ssw0rdS0pRi0T3c. This job is a strong candidate for privilege escalation via Docker image tampering or extraction.
- A privileged cleanup job that runs every minute:
This script executes as root. If I find a way to influence this script or its dependencies, I may achieve full privilege escalation. Next, I ran the netstat -tupln command to show active listening network services which allows me to find local services that aren't externally exposed:
Running
netstat -tupln
revealed that several services were only bound to 127.0.0.1
, including a suspicious one on port 8000
:Since the service wasn't accessible externally, I used SSH local port forwarding to tunnel traffic from my attacker machine to the internal port:
After entering the password, I was able to visit
http://localhost:8000
in my browser and interact with the internal service directly from my host system.Using the credentials obtained from crontab.db (P4ssw0rdS0pRi0T3c), I was able to log in to the webpage using the username root.
Accessing the Crontab UI via Web Interface
After gaining access to the crontab.db
file, I extracted the login credentials:
- Username:
root
- Password:
P4ssw0rdS0pRi0T3c
These credentials were likely stored for use with a local administrative interface. I navigated to http://127.0.0.1:8000, which turned out to be hosting a Crontab UI web application, a graphical frontend for managing cron jobs.
At the login prompt, I entered the extracted credentials. Authentication was successful, granting me full access to the cron job management panel.
Abusing Crontab UI for Privilege Escalation
Once logged in, I inspected the existing jobs and noticed that the interface allowed the creation of new cron jobs.
To escalate privileges or establish persistence, I added a new job titled revshell, and used the following command:
- cp /bin/bash /tmp/bash: Copies the bash binary to /tmp
- chmod u+s /tmp/bash: Applies the SetUID bit to the copied binary, allowing any user executing /tmp/bash to run it with root privileges
I scheduled this job to run every minute by setting the time expression to:
This action effectively gave me a root shell by simply executing /tmp/bash later with elevated privileges. After the cron job executed (as set in the Crontab UI), I checked the /tmp directory and found a file named bash:
Among other systemd-generated temporary files and log output (
*.stdout
, *.stderr
), the presence of the /tmp/bash
binary confirmed that the cron job successfully copied the system's Bash binary into the /tmp
directory and applied the SetUID bit:This SetUID bit allows the binary to execute with the permissions of its owner, which in this case is root
.
To confirm this, I ran the following command in the shell:
The
-p
flag preserves the privileged UID. The shell prompt changed, and running whoami
confirmed root access:Retrieving the Root Flag
With root access, I was able to read the flag stored in /root/root.txt
:
Hurray!!! I got the root flag
If you enjoy reading my writeup, please don't forget to subscribe to my mailing list and also follow me on my social media pages to get immediate notifications when I publish a new writeup. My socials are:
Twitter: https://x.com/Isiaq_Ibrahim99
Twitter: https://x.com/BoltechNG
0 Comments