我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 97.1% 的成绩。 了解更多

深度解析

深度解析

TightVNC Viewer 认证前 RCE,已在 2.8.90 修复

恶意 VNC 服务器可在任何密码提示之前在 TightVNC Viewer 上执行代码;请将 Viewer 升级到 2.8.90,并限制 TCP 5500 上的监听模式。

TL;DR

  • Windows 版 TightVNC Viewer 把像素缓冲区大小截断为 32 位。因此,宣布一个巨型屏幕的恶意 VNC 服务器可以在任何密码提示之前在 Viewer 上执行代码。SSD Secure Disclosure 于 2026 年 10 月 29 日连同可用的漏洞利用程序公布了该缺陷。
  • 2.8 系列中任何低于 2.8.89 的 Viewer 都受影响;研究人员在 2.8.88 x64 上演示了利用。使用监听模式的帮助台部署将 Viewer 暴露在 TCP 5500 上,既无密码也无 IP 限制,这使该缺陷成为认证前的远程代码执行。
  • 厂商在 2.8.89 和 2.8.90 中修复了 Viewer,分别于 2026 年 10 月 2 日和 10 月 5 日发布,并推荐 2.8.90。没有分配 CVE,没有厂商公告,也不知道有利用行为;截至 2026 年 11 月 2 日,该缺陷不在 CISA 的已知被利用漏洞(KEV)目录中。
  • 将每个 TightVNC Viewer 升级到 2.8.90。在升级到来之前,关闭监听模式或将 TCP 5500 限制为受信任主机,并绝不将 Viewer 指向不受信任的服务器;任何网络限制都无法覆盖第二条路径。

您是否受影响?

以下条件全部满足时,您处于暴露状态:

  • 机器运行 Windows 版 TightVNC Viewer,版本为 2.8.88 或 2.8 系列的任何更早版本。研究人员在 2.8.88 x64 上演示了利用,而阻止它的检查最早出现在 2.8.89 中。
  • 两条攻击路径之一可达。以 tvnviewer.exe -listen 或从托盘菜单启动的监听模式中,Viewer 绑定 0.0.0.0:5500 并接受任何连接的服务器,没有密码也没有 IP 限制。另外,用户将 Viewer 连接到攻击者控制或已被攻陷的服务器时,在连接瞬间、密码提示之前即被攻陷。
  • 攻击者能够到达 5500 端口(针对监听路径),或者能够运行或接管 Viewer 将要连接的 VNC 服务器。
分支 受影响版本 修复版本
TightVNC 2.8.x 至 2.8.88 2.8.90(2.8.89 修复了其中一部分)
Windows XP 时代主机上的 TightVNC 2.8.x 至 2.8.88 2.8.90,仍支持 XP 的最后一条系列
TightVNC 4.x 无公告;在修复之后发布 不适用;当前版本 4.0.2(2026 年 10 月 28 日)

2.8.88 版 Viewer 于 2026 年 6 月 19 日发布,因此截至 2026 年 11 月 2 日,受影响代码在当前安装中已存在 136 天;更早的安装携带它更久。披露材料将监听模式描述为"帮助台的常见部署方式",这使监听路径成为实际的暴露面。

检查已安装的 Viewer 版本以及是否在监听:

(Get-Item "C:\Program Files\TightVNC\tvnviewer.exe").VersionInfo.FileVersion
netstat -ano | findstr :5500

第一条命令输出默认安装中 Viewer 的文件版本;如果 TightVNC 安装在别处请调整路径。第二条输出任何监听 TCP 5500 的本地套接字,即暴露的监听模式;结果为空表示该路径已关闭。

如何修复?

将每个 TightVNC Viewer 升级到 2.8.90:

  1. 从厂商的下载页面下载适用于您平台的 2.8.90 安装程序并运行;它会就地替换 Viewer。
  2. 用上面的版本检查确认修复;文件版本必须显示 2.8.90。
  3. 重启任何以监听模式运行的 Viewer,使新二进制文件成为绑定 5500 端口的那个。

厂商自己的 2.8.90 版本通知写道,2.8.89 和 2.8.90 两个版本"解决了 Viewer 中的若干安全问题",并强烈建议使用 2.8.90。在升级落地之前,两个步骤可以收窄暴露,且都有局限:

  1. 在帮助台机器上关闭监听模式,或在防火墙上将 TCP 5500 限制为受信任 VNC 服务器的地址。局限很直白:缺陷仍在 Viewer 中,任何通往 5500 的不受信任路径都会让它保持敞开。
  2. 告诉操作人员绝不将 Viewer 连接到他们不控制的服务器。因为连接是出站的,任何网络限制都无法覆盖这条路径。

根本原因是什么?

Viewer 用一个被截断为 32 位的结果来决定像素缓冲区的大小。 随后的写入却使用从服务器宣布的完整尺寸推导出的偏移。代码位于 Viewer 的 rfb 层的 FrameBuffer 中,引自 2.8.88 源码发布。

大小计算在 64 位中相乘,然后丢弃超过 32 位的一切:

int FrameBuffer::getBufferSize() const
{
  return (int)((UINT64)m_dimension.area() * m_pixelFormat.bitsPerPixel / 8);
}

bool FrameBuffer::resizeBuffer()
{
  if (m_buffer != 0) {
    delete []m_buffer;
  }
  if ((m_buffer = new UINT8[getBufferSize()]) == 0) {
    return false;
  }
  return true;
}

宣布 32768 乘 32769、每像素 32 位屏幕的服务器使乘积回绕。64 位乘积超过 4 GB,(int) 强制转换只保留 128 KB,Viewer 分配 128 KB。存储的尺寸保留宣布的完整 32768 乘 32769,因此逻辑画布与分配恰好相差 2^32 字节(4,294,967,296)。

写入偏移随后在有符号 32 位 int 中、针对宣布的宽度计算,与已分配的大小不做任何比较:

void *FrameBuffer::getBufferPtr(int x, int y) const
{
  char *ptr = (char *)m_buffer;
  ptr += (y * m_dimension.width + x) * getBytesPerPixel();

  return (void *)ptr;
}

一个大的 y 使乘积回绕并做符号扩展,因此一个屏幕更新矩形可以将其像素放到缓冲区前后任意选定的偏移处。更新以 Raw 或 Tight 矩形的形式从服务器到达,经 RemoteViewerCore::receiveFbUpdateRectangle 进入解码器,而 RFB 协议允许服务器同时选择几何形状和每个矩形。

如何被利用?

公开的漏洞利用程序只需要一次连接,不需要任何凭据:

  1. 攻击者的 RFB 服务器向 Viewer 问候并提供唯一的安全类型 None。RFB 认证是单向的,服务器从不向 Viewer 证明自己,而 TightVNC 的 Viewer 接受 None。
  2. ServerInit 宣布被投毒的几何形状:32768 乘 32769、每像素 32 位。握手共 45 字节,并分配漏洞利用程序称为 FB1 的 128 KB 缓冲区。
  3. 坐标 (7492, 32767) 处的一个 Raw 矩形落在 FB1 - 0x18AF0,即位于帧缓冲区下方的一个 BufferedOutputStream 对象的 m_dataLength 字段。漏洞利用程序在此写入一个大值。
s.sendall(b"RFB 003.008\n")                 # greet as the server
s.sendall(bytes([1, 1]))                    # offer one security type: None
s.sendall(struct.pack(">I", 0))             # SecurityResult = OK
s.sendall(struct.pack(">HH", 32768, 32769)  # ServerInit: the poisoned geometry
          + PIXEL_FORMAT + struct.pack(">I", 3) + b"PWN")
  1. 下一次 flush() 通过套接字送回约 100 KB 的相邻堆内存。漏洞利用程序从这些字节恢复 tvnviewer.exe 的映像基址和帧缓冲区地址,从而击破地址空间随机化。
  2. 漏洞利用程序在 128 KB 帧缓冲区内写入伪对象和返回导向编程链,然后覆盖 BufferedOutputStream 的 vtable 指针。下一次虚函数调用跟随伪对象,将栈切换到帧缓冲区,链以 CreateProcessW 结束。

该利用程序对启用了 ASLR 和 DEP 的新版默认 Viewer 有效;二进制文件中没有控制流防护。披露材料公布了覆盖两条攻击路径(监听 Viewer 和出站连接)的完整利用脚本,包括每次运行后恢复 Viewer 的重启模式。

攻击如何流动?

攻击者只需要 Viewer 接受一个会话,截断的分配就把该会话变成对 Viewer 进程的控制。

flowchart LR A["攻击者运行恶意的
RFB 服务器"] --> B["Viewer 接受,
安全类型 None"] B --> C["ServerInit 宣布
32768 x 32769、32 bpp"] C --> D["缓冲区用 32 位计算,
128 KB 上的 4 GB 画布,
无边界检查"] D --> E["矩形写到
分配之外"] E --> F["堆泄露、vtable 劫持、
ROP 到 CreateProcessW:
在 Viewer 上执行代码"]

攻击者能做什么?

已证明的影响是在会话打开瞬间、以运行 Viewer 的账户权限在 Viewer 进程中执行代码:

  • 在监听模式下,任何能够到达 TCP 5500 的主机都能做到这一点,无需密码、无需 IP 允许列表、无需操作人员任何交互。披露材料将这种部署描述为帮助台的常见形态,因此暴露的是支持工具,而不是服务器。
  • 在出站连接上,攻陷发生在连接瞬间、任何密码提示之前,因此服务器端的 VNC 密码对已被接管的服务器毫无帮助。
  • 利用程序可以用 CREATE_NO_WINDOW 隐藏其载荷窗口,在执行后重新启动 Viewer,并可以随意让 Viewer 崩溃,构成拒绝服务。

条件是有限的:攻击者必须成为 Viewer 通信的服务器,或能够到达一个监听中的 Viewer。TightVNC 服务器 tvnserver 不是这里的目标;攻击的方向才是要点:被帮助的机器攻击提供帮助的机器。

修复为什么有效?

2.8.89 源码新增了文件 viewer-core/ViewerBufferSize.h,其中包含 64 位的大小谓词,并在任何分配之前验证服务器的宣告:

inline bool fitsFrameBuffer(int width, int height, int bytesPerPixel)
{
  if (width < 0 || height < 0 || bytesPerPixel <= 0) {
    return false;
  }

  const UINT64 alignedWidth = (static_cast<UINT64>(width) + 3) & ~static_cast<UINT64>(3);
  const UINT64 alignedHeight = (static_cast<UINT64>(height) + 3) & ~static_cast<UINT64>(3);
  return alignedWidth * alignedHeight <= INT_MAX / bytesPerPixel;
}

消费 ServerInit 几何形状的 RemoteViewerCore::setFbProperties 现在会在入口处拒绝它:

  if (!ViewerBufferSize::fitsFrameBuffer(width, height, bitsPerPixel / 8)) {
    throw Exception(_T("Framebuffer is too large"));
  }

同一模式保护富光标路径,2.8.89 中的 Tight 解码器也拒绝过大的 JPEG 矩形。2.8.90 中 Tight 解码器又增加了两项检查:拒绝解压后大小与声明的矩形不符的数据,以及空的压缩块。这些就是厂商版本通知点名的"Viewer 中的若干安全问题"。

该修复对已证明的路径是完整的。服务器宣告不再能到达被截断的分配,因为几何形状在缓冲区定尺寸之前就在协议边界被验证。截断算术本身仍留在 FrameBuffer::getBufferSize 中,在 2.8.90 里未作改动,因此安全性现在依赖每个调用方先做验证。这是向已验证入口的收窄,而不是缺陷类别的根除。

如何检查是否被入侵?

披露材料没有公布危害指标。攻击者的痕迹在 Viewer 主机上,下面的每一项检查都来自公开的攻击机制:

Get-WinEvent -LogName Application | Where-Object { $_.Message -match "tvnviewer" } | Select -First 20

应用程序日志中无法解释的 Viewer 崩溃标志着拒绝服务变种。利用程序的载荷作为 Viewer 的子进程运行,因此请在进程创建遥测中检查任何父进程为 tvnviewer.exe 的进程。在启用 Sysmon 的主机上,带该父进程的事件 ID 1 就是查询。

在监听 Viewer 上,检查网络日志中到达 TCP 5500 的入站连接,以及随后来自 Viewer 的约 100 KB 出站突发。该突发就是利用程序回读的堆泄露。

如果某个 Viewer 曾暴露并出现任何这些迹象,请将操作人员的账户视为已被攻陷,并轮换该账户能够触及的一切。

时间线

  • 2026-06-19:发布作为已证明受影响版本的 TightVNC 2.8.88。
  • 2026-10-02:TightVNC 2.8.89 增加了对超大帧缓冲区、RichCursor 更新和 Tight JPEG 矩形的检查;厂商建议升级。
  • 2026-10-05:TightVNC 2.8.90 携带其余 Viewer 修复,验证解压大小并拒绝空压缩块;源码带有该日期。
  • 2026-10-29:SSD Secure Disclosure 公布分析和利用程序,功劳归于 SSD Labs Korea 的 SeongJoon Cho,并报告厂商从未回复其报告。
  • 2026-11-02:没有分配 CVE,没有厂商公告,也不知道有利用行为;该缺陷不在 CISA 的 KEV 目录中。

修复在受影响的 2.8.88 发布 105 天后、利用程序公开前 24 天发布
图 1:6 月 19 日的受影响版本、10 月 2 日和 10 月 5 日的两个修复,以及 10 月 29 日的公开利用程序。来源:tightvnc.com 发行说明和 SSD Secure Disclosure,2026 年 11 月 2 日核查

FAQ

TightVNC 服务器也受影响吗?

不受影响。目标是 Viewer,即 tvnviewer.exe,攻击从服务器流向 Viewer。只运行 TightVNC 服务器的主机,仅在其操作人员也使用 Viewer 向外连接的程度上暴露。

VNC 密码能阻止它吗?

不能。Viewer 接受安全类型 None,而 RFB 认证本来就不会向 Viewer 证明服务器的身份。出站路径在任何密码提示之前完成,因此真实服务器上的强密码在该服务器变成攻击者的服务器后毫无用处。

这一类缺陷以前在 TightVNC 上发生过吗?

发生过,两次都来自恶意服务器。TightVNC 1.3.10 修复了 Core Security Technologies 报告的 Viewer 整数溢出,该问题允许被篡改的 VNC 服务器破坏 Viewer 的堆。2.8.63 版修复了一个缓冲区溢出,允许"恶意的"服务器在 Viewer 所在机器上执行代码。厂商自己的发行说明记录了这两次。

TightVNC 4 受影响吗?

没有公告涵盖 4.x 系列。该系列于 2026 年 10 月 25 日发布,晚于 2.8.89 和 2.8.90 修复。4.0 公告描述的是新的安全模型,而不是这个 Viewer 缺陷。如果您运行 4.x,请向厂商确认;在 2.8.x 上,无论如何都应升级到 2.8.90。

为什么没有 CVE?

厂商不发布公告,研究人员的报告未获答复,因此截至 2026 年 11 月 2 日没有分配 CVE。依赖项和漏洞扫描器因此无法标记受影响范围;"您是否受影响?"中的版本检查是唯一可靠的检测手段。

在哪里获得修复后的 Viewer?

在厂商的下载页面,该页面与 4.0.2 系列一起提供 2.8.90 安装程序。2.8.90 源码以 GPL 在同一位置发布,本文的修复分析正来自那里。

用 Ostorlab 找到暴露监听 Viewer 的主机

Ostorlab 的攻击面发现会盘点您面向互联网的主机,从而找出哪些支持机器在 TCP 5500 上以监听 Viewer 应答,并优先升级它们。

参考文献

  • SSD Secure Disclosure,"TightVNC Viewer Pre-auth RCE",分析与利用程序,功劳归于 SSD Labs Korea 的 SeongJoon Cho:https://ssd-disclosure.com/tightvnc-viewer-pre-auth-rce/(2026 年 10 月 29 日发布;2026 年 11 月 2 日核查)
  • TightVNC 发行说明,2.8.89 和 2.8.90 中的 Viewer 修复:https://www.tightvnc.com/whatsnew.php(2026 年 11 月 2 日核查)
  • TightVNC 新闻,10 月 2 日与 10 月 5 日的发布公告以及 6 月 19 日的 2.8.88 发布:https://www.tightvnc.com/news.php(2026 年 11 月 2 日核查)
  • TightVNC 下载页面,2.8.90 与 4.x 安装程序及 GPL 源码归档:https://www.tightvnc.com/download/(2026 年 11 月 2 日核查)
  • TightVNC 2.8.88 源码发布,脆弱的 FrameBuffer:https://www.tightvnc.com/download/2.8.88/tightvnc-2.8.88-src-gpl.zip(2026 年 11 月 2 日核查)
  • TightVNC 2.8.90 源码发布,ViewerBufferSize.h 与验证调用点:https://www.tightvnc.com/download/2.8.90/tightvnc-2.8.90-src-gpl.zip(2026 年 11 月 2 日核查)
  • CyberSecurityNews,"TightVNC Pre-Auth RCE Vulnerability Lets Hackers Execute Code on Windows PCs, PoC Released":https://cybersecuritynews.com/tightvnc-pre-auth-rce-vulnerability/(2026 年 11 月 2 日发布;2026 年 11 月 2 日核查)
  • CISA 已知被利用漏洞目录,针对 TightVNC 条目核查:https://www.cisa.gov/known-exploited-vulnerabilities-catalog(2026 年 11 月 2 日核查)