What this actually is.
Technical background, root cause, and affected surface.
UltraVNC MS-Logon II uses DH_MAX_BITS=31 (dh.h:44), key space only 2^31. Private exponent is generated by rng()=rand()*rand()*rand()%maxNum seeded with srand(time(NULL)). BSGS key recovery is live-confirmed in 0.010 seconds from a captured handshake. The attacker recovers the shared key and decrypts the Windows username and password in transit.
- Vendor
- UltraVNC
- Product
- UltraVNC
- Severity
- High
- CVSS Score
- 7.4
- Status
- Fixed
- Vector
- CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- CWE
- CWE-326: Inadequate Encryption Strength, CWE-338: Use of Cryptographically Weak PRNG
From one request
to root shell.
Reproduced in a sandboxed environment. Requires only LAN or WiFi adjacency.
BSGS key recovery tool: live confirmed gen=1628590949 mod=2119336411 pub=480274997 → private key 983298996 recovered in 0.010s and verified. predict_challenge.py (private) demonstrates deterministic exponent prediction.
The bug, and the fix.
unsigned __int64 rng(unsigned __int64 limit) { return ((((unsigned __int64) rand()) * rand() * rand()) % limit); // dh.cpp:63 } // DH_MAX_BITS=31 (dh.h:44); srand(time(NULL)) at dh.cpp:53 unsigned __int64 maxNum = ((unsigned __int64) 1) << DH_MAX_BITS; // 2^31
Root cause: DH_MAX_BITS set to 31 (not 2048+). RNG uses libc rand() with time-based seed. Design acknowledged as insufficient by original author in 2006. libsodium is already pinned in vcpkg.json.
When does this fire?
All conditions must be true for the exploit to succeed.
Target authenticates using MS-Logon II. 2. Attacker captures DH handshake (generator, modulus, public key) on the wire. 3. BSGS algorithm recovers private exponent in <1 second. 4. Shared key derived; MS-Logon II challenge/response decrypted → plaintext credentials.
What an attacker does to you.
Post-exploitation outcomes mapped to CVSS impact metrics.
Plaintext Windows domain username and password exposed to any passive network observer or MITM. Affects all UltraVNC deployments using MS-Logon II on non-encrypted networks.
Fix it. In this order.
A runbook, not a checklist. Sequence matters — assume compromise before you act.
Upgrade to MS-Logon III (X25519+AES-256-GCM via libsodium). Vendor fix: MS-Logon III introduced as preferred path; MS-Logon II retained as backward-compat fallback with runtime security warning when activated.
disclose@securin.ioVendors moved in days.
Attackers in hours.
Reconstructed from vendor advisories, CISA bulletins, and Securin research records.
Timeline recorded · Disclosure coordinated by Securin
Cite, verify, go deeper.
Primary sources — NVD, CISA KEV, and machine-readable IoC feed.