What this actually is.
Technical background, root cause, and affected surface.
In vncviewer/ClientConnection.cpp, the 4-byte network-supplied reasonLen is passed as reasonLen+1 to CheckBufferSize(). With reasonLen=0xFFFFFFFF, unsigned addition wraps to 0, allocating 256 bytes. ReadString(m_netbuf, reasonLen) then performs ReadExact for the original 4 GiB into the 256-byte buffer. ASan confirms 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.
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.
Timeline recorded · Disclosure coordinated by Securin
Cite, verify, go deeper.
Primary sources — NVD, CISA KEV, and machine-readable IoC feed.