What this actually is.
Technical background, root cause, and affected surface.
UltraVNC viewer through 1.8.2.2 contains an integer overflow leading to a heap buffer overflow in the RFB protocol failure-response parsing path. In vncviewer/ClientConnection.cpp, the 4-byte network-supplied reasonLen field (type CARD32) is passed as reasonLen+1 to CheckBufferSize(). Because both operands are unsigned 32-bit, a reasonLen of 0xFFFFFFFF overflows to 0, causing CheckBufferSize to allocate only 256 bytes. The subsequent ReadString(m_netbuf, reasonLen) call then performs ReadExact for the original 4 GiB length into that 256-byte heap buffer. This overflow is reachable via rfbConnFailed (auth-scheme negotiation) and rfbVncAuthFailed (post-handshake) message types without successful authentication. A malicious VNC server, or any man-in-the-middle on the RFB stream, can trigger this condition when the victim viewer connects, potentially resulting in remote code execution as the user running the viewer. The crash was confirmed with AddressSanitizer on a portable reproduction harness (heap-buffer-overflow WRITE at offset 256).
- Vendor
- UltraVNC
- Product
- UltraVNC Viewer
- Severity
- High
- CVSS Score
- 8.8
- Status
- Fixed
- Vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
- CWE
- CWE-190: Integer Overflow to Buffer Overflow, CWE-787: Out-of-bounds Write
From one request
to root shell.
Reproduced in a sandboxed environment. Requires only LAN or WiFi adjacency.
poc_finding010_viewer_vendor.py: minimal malicious RFB server sends rfbConnFailed with reasonLen=0xFFFFFFFF. ASan output: heap-buffer-overflow on 0x511000000140, WRITE of size 1 at offset 256. Crash-trigger only.
The bug, and the fix.
ReadExact((char *)&reasonLen, 4); // attacker source reasonLen = Swap32IfLE(reasonLen); // 0xFFFFFFFF CheckBufferSize(reasonLen+1); // UINT overflow → 0 → alloc 256 bytes ReadString(m_netbuf, reasonLen); // reads 4 GiB into 256-byte heap buffer
Root cause: CheckBufferSize() parameter is UINT; reasonLen+1 causes unsigned integer overflow at 0xFFFFFFFF. Legacy dead-code guard (if bufsize<0) cannot trigger for UINT. ReadString uses original unmodified reasonLen.
When does this fire?
All conditions must be true for the exploit to succeed.
Victim viewer connects to attacker host:port (or clicks vnc://attacker link). 2. RFB version handshake completes. 3. Attacker sends authScheme=0x00000000 (rfbConnFailed). 4. Attacker sends reasonLen=0xFFFFFFFF. 5. UINT overflow → 256-byte alloc → ReadExact(4GB) → heap corruption.
What an attacker does to you.
Post-exploitation outcomes mapped to CVSS impact metrics.
Heap buffer overflow in vncviewer.exe. Controlled write of up to 4 GB into 256-byte heap allocation. RCE candidate. ASan-confirmed crash.
C:H · I:H · A:H
CWE-190: Integer Overflow to Buffer Overflow, CWE-787: Out-of-bounds Write
Fix it. In this order.
A runbook, not a checklist. Sequence matters — assume compromise before you act.
Reject reasonLen > 4095 before CheckBufferSize. Change CheckBufferSize parameter to size_t. Audit all CheckBufferSize(x+n) sites. Vendor fix: if (reasonLen > 4095) throw guard added at both rfbConnFailed and rfbVncAuthFailed paths.
disclose@securin.ioVendors moved in days.
Attackers in hours.
Reconstructed from vendor advisories, CISA bulletins, and Securin research records.
Discovered and ASan crash-confirmed
Reported to vendor
Fix validated
Planned public disclosure
Timeline recorded · Disclosure coordinated by Securin
Cite, verify, go deeper.
Primary sources — NVD, CISA KEV, and machine-readable IoC feed.