本文是卡巴斯基实验室发布的关于开源的远程访问系统虚拟网络计算 (VNC)中的漏洞研究文章。研究人员从中发现了多个内存损坏漏洞并被分配了37个 CVE漏洞。其中一些漏洞如遭利用可导致远程代码执行后果。奇安信代码卫士团队翻译如下。

准备工作

VNC 系统旨在为设备提供访问另外一台设备屏幕的远程访问权限。值得一提的是,该协议的标准并未限制操作系统的选择,而是允许跨平台实现。常见的操作系统如 GNU/Linux、Windows、安卓和其它不太常用的系统都可实现。

VNC 已成为使用最广泛的系统之一,部分得益于跨平台实现和开源许可证。该系统确切的安装量难以预测。从 shodan.io 网站的数据来看,网络上存在超过60万台 VNC 服务器。如果加上本地网上的设备,那么可以肯定的是处于使用状态中的 VNC 服务器数量要多得多。

数据显示,VNC 活跃使用于工控自动化系统中。卡巴斯基在最近发布的关于工控系统中远程管理工具的文章中提到,多种远程管理工具如 VNC 安装在大约32%的工控系统计算机中。在18.6%的案例中,这些工具包含在 ICS 软件分布数据包中并 VN配有VNC 软件。余下的81.4%的远程管理工具显然是由这些企业中的诚实或不那么诚实的员工或其合同工安装的。在此前的攻击案例中,我们分析发现攻击者安装并使用了远程管理工具。更重要的是,在某些情况下,这些攻击者利用这些远程管理工具中的漏洞作为部分攻击场景。

我们预测,多数工控供应商为基于 VNC 而非其它系统实现远程管理工具。于是,我们选择优先分析 VNC 系统的安全性。

Windows 系统中的某些 VNC 服务器组件以服务的形式实现,提供优先的系统访问权限,意味着它们本身具有对系统的高度访问权限。而这也是选择优先分析 VNC 安全性的另外一个原因。

系统说明

VNC 系统旨在向操作系统的用户接口(桌面)提供远程访问权限。VNC 使用 RFB(远程框架缓冲区)协议在设备间传输屏幕图像、鼠标动作以及按键事件。按照规则要求,系统的每种实现都包括一个服务器组件和一个客户端组件。由于 RFB 协议是客户端标准化的不同的实现,而服务器部件是可交换的。服务器组件将服务器桌面的图像发送到客户端以供查看,而客户端会将客户端事件(如鼠标光标活动、按键、经由剪切缓冲区的数据复制和粘贴)传回服务器。这就使得客户端上的用户在运行 VNC 服务器的远程机器上进行工作。

远程机器桌面每次更新(比如客户端动作触发时更新)时,VNC 服务器都会发送一张图像。发送新的完整的截屏显然是相对的资源密集型操作,因此 RFB协议不会发送整张截屏,而是只更新因某些动作或事件更改而发生变化的像素。 RFB 同时支持多种屏幕更新压缩以及编码方法。比如,压缩可通过 zlib 或 RLE 执行。

尽管 VNC 软件旨在执行简单任务,但它的功能足够广泛,使程序员在开发阶段犯错。

可能的攻击向量

由于 VNC 系统由服务器和客户端组件构成,因此我们主要关注两种主要的攻击向量:

1、攻击者和 VNC 服务器位于同一网络,并试图攻击 VNC 服务器来获得以服务器权限在服务器上执行代码的能力。

2、用户通过 VNC 客户端连接到攻击者服务器上,而攻击者利用客户端中的多个漏洞攻击用户并在用户机器上执行代码。

毫无疑问,攻击者会选择在服务器上远程执行代码。然而,多数漏洞存在于该系统的客户端组件中。产生这种结果的部分原因是客户端组件中包含旨在解码所有格式的服务器发送的数据。正是编写解码组件的数据通常导致开发人员犯错才导致内存损坏漏洞问题。

另一方面,服务器的代码基相对较小,旨在将编码的屏幕更新发送给用户并处理从客户端收到的事件。根据标准规定,服务器必须只支持六种消息类型才能为运营提供所有的所需功能。这意味着多数服务器组件几乎不具有复杂功能,从而减少了开发人员犯错的几率。然而,某些系统中执行了多种扩展来增加服务器的功能,如文件传输、客户端和服务器之间的聊天等。如研究结果所证明的那样,主要的错误正是在旨在增加服务器功能的代码中产生的。

研究对象

我们在研究中选择了最常见的 VNC 实现:

  • LibVNC:一款用于创建基于 RFB 协议的自定义应用程序的开源跨平台库。LibVNC 的服务器组件用于在 VirtualBox 中通过 VNC 提供对虚拟机的访问权限。

  • UltraVNC:一款专门为 Windows 开发的热门开源 VNC 实现。很多工业自动化公司推荐该实现通过 RFB 协议连接远程 HMI 接口。

  • TightVNC:RFB 协议的更为流行的实现。很多工业自动化系统供应商推荐通过 *nix 机器连接到 HMI 接口。

  • TurboVNC:一款开源的 VNC 实现。使用 libjpeg-turbo 库压缩 JPEG 图像,加快图像传输速度。

在研究过程中,我们并未没有分析一款非常流行的产品 RealVNC 的安全性,因为该产品的许可证禁止进行逆向分析。

此前的研究工作

在开始分析 VNC 实现前,很有必要做一些侦察工作并查看每种实现中已经识别出的漏洞问题是什么。

2014年,谷歌安全团队发布了一份简短的 LibVNC 漏洞分析报告。由于该项目中的代码量很小,因此可以假设谷歌工程师已经识别出 LibVNC 中的所有漏洞问题了。然而,我还从2014年以后发布的GitHub 版本中找到了多个问题。

UltraVNC 项目中的漏洞数量并不多。其中多数漏洞都和具有任意长度数据的简单的栈溢出被写入栈固定长度缓冲区有关。

这些已知漏洞都是在很久之前发现的。此后,该项目的代码基已经扩大,而老旧的代码基中仍然含有老旧漏洞问题。

研究结果

LibVNC

分析完此前找到的漏洞问题后,我在用于提供文件传输功能的扩展代码中发现了其中某些漏洞的变体。该扩展并非默认启动:开发人员必须明确允许在基于LibVNC 的项目中使用它。这可能就是此前为何这些漏洞未被找到的原因所在。

接着,我开始从分析服务器代码转向研究客户端。我正是从客户端中找到了对于项目而言最重要的也是变体最多的漏洞问题。

在所发现的漏洞中,值得注意的是将在其它基于 RFB 协议的项目中出现的多种漏洞类型。

可以说,这些漏洞类型都是因 RFB 协议的标准设计方式而造成的。更确切地说,该协议的标准设计方式并无法确保开发人员防御这类漏洞类型,从而导致此类缺陷产生。

为说明这一点,我们可以查看 VNC 项目中使用的结构来处理网络消息。例如,打开 rfbproto.h 文件发现,LibVNC 项目中包含多种文件,其中一种是(https://github.com/LibVNC/libvncserver/blob/e0a9d96d56f1cbb99f71d97491102192d2ee4ee4/rfb/rfbproto.h#L21)。rfbproto.h 文件是1999年以来数代 VNC 项目开发人员都在使用的文件。

rfbClientCutTextMsg 结构是说明第一种漏洞类型的绝佳例子。该结构用于将客户端上剪切缓冲区变化的信息发送给服务器。

    typedef struct {uint8_t type;/* always rfbClientCutText */uint8_t pad1;uint16_t pad2;uint32_t length;/* followed by char text[length] */} rfbClientCutTextMsg;

    在建立连接并执行首次握手后,该客户端以及服务器同意使用特定的屏幕设置,所有传输的信息都具有相同的格式。每条信息都以一个字节开头代表该信息的类型。根据消息类型会选择匹配该类型的消息处理器和结构。在不同的 VNC 客户端中,该结构被以几乎同样的方式进行填充(C伪代码):

      ReadFullData(socket, ((char *)&msg) + 1, sz_rfbServerSomeMessageType – 1);

      整个消息结构以这种方式填充,除了第一个用于定义消息类型的字节外。可以看到,该结构中的所有字段都由远程用户控制。还应该注意到的是,msg是一个 union,由所有可能的信息结构构成。

      由于剪切缓冲区的内容的长度不确定,因此会使用 malloc 动态分配内存。值得推荐的是,该剪切缓冲区字段应当包含文本并且在C语言中会通过0字符终止文本数据。鉴于这一点以及字段 length 具有unit32_t类型且由远程用户完全控制的事实,在这个案例中,我们具有一种典型的整数溢出问题(C伪代码):

        char *text =malloc(msg.length +1);ReadFullData(socket, text, msg.length);text[msg.length] =0;

        如果攻击者以等同于UINT32_MAX = 232– 1 = 0xffffffff 的值发送到消息长度字段中,那么这个整数溢出漏洞就会调用malloc(0) 函数。如果使用了标准的 glibc malloc 内存分配机制,那么该调用会返回最小可能大小,即16字节。同时,等于UINT32_MAX 的长度将会被传递到ReadFullData 函数中作为参数,如果在 LibVNC 案例中,它会导致堆缓冲区溢出问题。

        第二种漏洞类型可在同样的机构中进行演示。RFC 标准规定,某些结构包括用于字段对齐的填充。然而,从安全研究员的角度看,它是又一个发现内存初始化错误的机会。我们来看下这种错误(C伪代码):

          rfbClientCutTextMsg cct;cct.type = rfbClientCutText;cct.length =length;WriteToRFBServer(socket, &cct, sz_rfbClientCutTextMsg);WriteToRFBServer(socket, str, len);

          消息结构创建于栈上,之后它的某些字段被填充,而该结构被发送到服务器。可以看到,结构 pad1和 pad2 仍然是空的。因此,通过网络发送一个未初始化变量后,攻击者能够从栈中读取未初始化内存。如果攻击者走运的话,攻击者能访问的内存区域可能包括堆、栈或文本部分的地址,从而使攻击者能够绕过 ASLR 并使用溢出在客户端实现远程代码执行。

          这类小漏洞问题时不时地就会出现在 VNC 项目中,这也是我们将它们单列出来的原因所在。

          值得注意的是,分析像 LibVNC 项目这样被当做跨平台解决方案的项目并非易事。在分析这类项目的过程中,我们应当忽略和具体操作系统和研究人员计算机架构相关的任何内容并通过 C语言标准的棱镜来广泛地查看该项目,否则很容易丢掉该代码中的一些显而易见的但只能在某种特定平台上重现的缺陷问题。例如,在本案例中,该堆溢出漏洞被错误地在32位平台上修复,因为 x86_64平台上的大小或 size_t 类型不同于32位 x86 平台上同样类型的大小。

          所有已识别漏洞的信息已同步给开发人员,且漏洞已解决。

          TightVNC

          研究的下一个目标是非常流行的 GNC/Linux 的热门 VNC 客户端实现。

          我能够很快地从该系统中找到多个漏洞,原因是多数漏洞是非常直观的,而且类似于 LibVNC 中的漏洞。这两种不同项目的两个代码片段对比如下:

          一开始,该漏洞是从 LibVNC 项目的 CoRRE 解码方法中发现的。在如上的代码片段中,任意长度的数据被读入rfbClient 结构固定长度的缓冲区中。它自然导致缓冲区溢出问题。但巧合的是,函数指针都位于结构内部,几乎就紧跟在剪切缓冲区之后,它几乎立即导致代码执行后果。

          可以看到,除了某些魏霞的差别外,LibVNC 和 TightVNC 的代码片段是非常相似的。两个代码片段都是从 AT&T Laboratories 中复制的。开发人员早在1999年就已经引入该漏洞(通过 AT&T Laboratories 许可证即可判断出。在许可证中,开发人员通常会列出在项目的不同开发时期的参与人员。)自此之后该代码就被数次修改。例如,在 LibVNC 中该静态全局缓冲区被迁移到客户端结构中,但所有修改均未能消除这个漏洞。

          还有一点值得注意的是, HandleCoRREBPP 的名称非常久远。如果在 GitHub 上搜索项目代码中这个字符组合,就会发现很多 VNC 相关项目都会不加思考地复制带有这个名称或整个 LibVNC 库的易受攻击的价码函数。这也是这些项目为何仍然永远易受攻击的原因所在,除非开发人员更新项目内容或者自己修复代码漏洞之外别无他法。

          字符组合 HandleCoRREBPP 实际上并非函数名称。这个案例中的 BPP 代表的是“Bits per Pixel(每个像素中的位)”,它是一个等于8、16或32的数字,具体是哪个数字取决于客户端和服务器在初始化阶段同意的颜色深度。开发人员应该会在宏中将该文件用作辅助文件,如下:

            #ifndef HandleCoRRE8#define BPP 32#include ”corre.h”#undef BPP#endif

            结果是多个函数:HandleCoRRE8、HandleCoRRE16 和HandleCoRRE32。

            由于该程序原来是由 C 而非 C++ 编写而成,因此开发人员必须具备这类技术,因为并不存在可用的模板。然而,如果你从谷歌上搜索函数名称HandleCoRRE 或HandleCoRRE32,你会发现很多项目都均存在些许修改,或者使用或者不使用模式,但它们仍然包含该漏洞。遗憾的是,数百个项目从未做出任何修改就进行复制,联系所有的开发人员谈何容易。

            TightVNC 的悲惨经历尚未结束。当我们将这些漏洞问题告知 TightVNC 开发人员后,他们表示感谢并指出已经停止对 TightVNC 1.X 线的开发且不再修复已发现的任何问题,因为修复对于公司是不具有商业性的做法。值得注意的是,TightVNC 2.X 的 Unix 系统版本仅在商业许可证下分发,且不再以开源软件的形式发布。

            我们发出 TightVNC 漏洞报告并强调称数据包维护人员应该自行修复漏洞。尽管我们早在2019年1月就已经通知到数据包维护人员,但到本文发稿前这些漏洞仍未修复。

            TurboVNC

            这个 VNC 项目值得“特别”嘉奖:它包含了一个让人头疼的漏洞问题。

            看下源自用于处理用户信息的主服务器函数的一个 C 代码片段:

              chardata[64];READ(((char *)&msg) + 1,sz_rfbFenceMsg – 1)READ(data,msg.f.length)if (msg.f.length >sizeof(data))rfbLog("Ignoringfence.Payloadof %dbytesistoolarge.\n",msg.f.length);elseHandleFence(cl,flags,msg.f.length,data);return;

              这个代码片段以 rfbFenceType 格式读取信息。该信息为服务器提供关于紧跟信息的类型uint8_t 用户数据长度 msg.f.length 的信息。很显然,它是任意用户数据被读入固定大小缓冲区从而导致栈溢出的问题。重要的是,数据被读取到缓冲区后会检查所读数据的长度。

              由于栈中缺乏溢出防护措施(所谓的金丝雀),该漏洞导致能够控制返回地址并随后实现在服务器远程执行代码的后果。然而,攻击者首先需要获取认证凭证来连接 VNC 服务器或者在建立连接前获得对客户端的控制。

              UltraVNC

              在 UltraVNC 中,我在该项目的服务器和客户端组件中找到了多个漏洞,共被分配了22个 CVE 编号。

              该项目的一个显著特征是聚焦 Windows 系统。在分析可为 GNU/Linux 编译的项目时,我选择两种不同的漏洞搜索方法。第一,我分析了代码并查找其中的漏洞。第二,我试图分析出如何通过模糊测试自动化搜索项目漏洞。我在分析 LibVNC、TurboVNC 和 TightVNC 时都这样做了。对于这类项目,由于项目并不依赖于某个具体操作系统对网络 API 的实现(另有其他抽象层进行实现),因此很容易就为 libfuzzer 编写了一个封装。为了写一个良好的模糊检测器,需要做的就是自己实现目标函数并重写网络函数。这就导致模糊测试的数据填入程序,就像从网络传输那样。

              然而,在分析 Windows 版本的项目时,后一种技术甚至难以用于开源项目中,因为相关工具要么不可用要么开发不良。当时分析时, Windows 版本的 libfuzzer 尚未发布。另外,用于 Windows 应用程序开发中的基于事件的方法意味着必须重写大量代码才能获得良好的模糊测试覆盖。因此,在分析 UltraVNC 中的漏洞问题时,我只使用了手动代码分析的方法。

              结果发现 UltraVNC 中的漏洞够一个“动物园”了,从不起眼的 strcpy 和 sprintf 中的缓冲区溢出漏洞到严重程度有高有低的可被用于实际项目中的漏洞不一而足。接下来我们讨论其中的某些漏洞问题。

              CVE-2018-15361

              这个漏洞存在于 UltraVNC 客户端代码中。在初始化阶段,服务器应当提供关于显示高度和宽度、颜色深度、调色板和桌面名称的信息,而它们可被显示在窗口等标题栏中。

              桌面名称是长度未定义的字符串。之后该字符串的长度被首先发送给客户端,之后是字符串本身。如下是相关的代码片段:

                void ClientConnection::ReadServerInit(){ ReadExact((char *)&m_si, sz_rfbServerInitMsg); m_si.framebufferWidth = Swap16IfLE(m_si.framebufferWidth); m_si.framebufferHeight = Swap16IfLE(m_si.framebufferHeight); m_si.format.redMax = Swap16IfLE(m_si.format.redMax); m_si.format.greenMax = Swap16IfLE(m_si.format.greenMax); m_si.format.blueMax = Swap16IfLE(m_si.format.blueMax); m_si.nameLength = Swap32IfLE(m_si.nameLength); m_desktopName =new TCHAR[m_si.nameLength +4 +256]; m_desktopName_viewonly =new TCHAR[m_si.nameLength +4 +256+16]; ReadString(m_desktopName, m_si.nameLength);. . .}

                细心的读者可能已经发现如上代码中存在一个整数溢出漏洞。然而,在本案例中,该漏洞并不会导致ReadString函数中产生堆缓冲溢出漏洞,而是导致更严重的后果发生。

                  void ClientConnection::ReadString(char *buf,intlength){if (length >0) ReadExact(buf,length); buf[length] ="\0";}

                  我们可以看到,ReadString 函数旨在读取字符串长度 length 并通过一个0字符串终止。值得注意的是,该函数将有符号类型作为第二个参数。

                  如果我们指定m_si.nameLength中一个非常大的数字,那么它在传入ReadString函数作为一个参数时会被当做负数对待。这就会导致length无法通过误报检测,而 buf 数字仍然未被初始化。结果只会发生一件事情:空字节将以偏移buf+ 长度写入。假设长度为负数,则以相对于 buf 以固定的负偏移量写入空字节。

                  结果是,当分配m_desktopName 且缓冲区在该进程的常规堆上进行分配时如果发生整数溢出漏洞,那么会导致空字节写入前一个代码块。如果没有发生整数溢出漏洞且系统内存足够,那么就会分配更大的缓冲区且被分配新的堆。远程攻击者通过正确的参数能够在 _NT_HEAP 结构中写入一个空字节,而该字节会直接位于庞大的代码块之前。该漏洞必定会引发拒绝服务攻击,但能否引发远程代码执行还尚未有定论。我不排除有些安全专家能够利用这个 Windows userland 堆的漏洞将它转换为远程代码执行漏洞的可能性。

                  CVE-2018-8262

                  该漏洞是在通过 Ultra 编码的数据处理器中发现的。它表明该功能的安全性和可用性真的是一线牵。

                  该处理器使用的是 minilzo 库的lzolx_decompress 函数。要理解该漏洞是什么,我们必须首先看下压缩和解压缩函数的原型。

                  要调用解压缩函数,我们必须传递包含压缩数据的缓冲区、压缩数据的长度、数据应当被解压缩的缓冲区及其作为输入的长度。需要记住的一点是,如果输入的数据无法被加压缩,那么函数会返回错误。另外,开发人员需要了解将被加压到输出缓冲区的数据的确切长度。也就是说,除了出错代码外,该函数应当返回等通过缩写字节数量的值。例如,用于传递写入缓冲区长度的函数可用于此目的,前提是它是由指针传递的。在上述案例中,解压缩函数的最小接口应该像下面这样:

                    intdecompress(constunsignedchar *in,size_t in_len,unsignedchar *out,size_t *out_len)

                    该函数的前四个参数和lzolx_decompress函数的前四个函数一样。

                    我们看下包含严重的堆缓冲漏洞的 UltraVNC 代码的片段:

                      void ClientConnection::ReadUltraRect(rfbFramebufferUpdateRectHeader *pfburh) {UINT numpixels = pfburh->r.w * pfburh->r.h;UINT numRawBytes = numpixels * m_minPixelBytes;UINT numCompBytes; lzo_uint new_len; rfbZlibHeader hdr;// Read in the rfbZlibHeader omni_mutex_lock l(m_bitmapdcMutex); ReadExact((char *)&hdr, sz_rfbZlibHeader); numCompBytes = Swap32IfLE(hdr.nBytes); CheckBufferSize(numCompBytes); ReadExact(m_netbuf, numCompBytes); CheckZlibBufferSize(numRawBytes); lzo1x_decompress((BYTE*)m_netbuf,numCompBytes,(BYTE*)m_zlibbuf,&new_len,NULL); . . .}

                      我们可看到,UltraVNC 开发人员并未检查 lzolx_decompress返回代码,不过它和另外一个缺陷即不当使用 new_len 而言微不足道。

                      未初始化变量new_len 被传给 lzolx_decompress 函数。在调用该函数时,该变量应当等同于m_zlibbuf 缓冲区的长度。另外,当调试vncviewer.exe(从 UltraVNC 官网 build 中拿到的可执行文件)时,我发现了为何这个代码会通过测试阶段的原因。事实证明,当未初始化变量 new_len 时,它包含大量文本部分地址值。从而使远程用户能够将特别编制的数据作为输入传入解压缩函数中以保证该函数在写入m_zlibbuf 缓冲区时,写入的数据将超出缓冲区边界,从而导致堆溢出问题。

                      结论

                      在结论部分,我想说在进行研究的过程中,我不禁想我找到的这些漏洞是不是都太简单了,所以之前会被其他人错过。然而,这真的是真的。所有这些漏洞的生命周期都非常长久。

                      研究中提到的某些漏洞类型存在于大量开源项目中,它们甚至在代码库重构后仍然存在。我认为能够同步找到包含并不一定总是以明确方式继承的漏洞的易受攻击项目非常重要。

                      几乎以上分析的项目都没有进行单元测试;并未通过静态代码分析或模糊测试方法对程序进行同步测试。代码中丰富的魔力常数就像一个纸牌屋:这个不稳定结构中只要有一个常数更改就会导致新漏洞的产生。

                      如果开发人员和厂商在产品中使用了第三方 VNC 项目代码,那么我们建议:

                      • 在所有使用的第三方 VNC 项目中设置漏洞追踪机制并例行更新代码版本。

                      • 增加编译选项,使攻击者更难以利用可能存在的代码漏洞。即使研究人员无法检测出项目中的任何漏洞问题,但应该尽量使它们更难以被利用。

                      例如,如果项目被编译为独立于位置的可执行文件 (PIE),那么文中的某些漏洞就不可能被利用实现远程代码执行。漏洞可能仍然存在,但利用只会导致拒绝服务而非远程代码执行。

                      另外一个案例是,TurboVNC 的糟糕体验:该编译器有时候会优化检查栈金丝雀的程序。某些编译器会通过从并未明确分配数组的函数中删除栈金丝雀检测的方式执行优化。然而,TurboVNC 可能会出错,并在栈的某些结构中或 switch-case 语句中未能检查缓冲区是否存在。为了使用已识别漏洞变得更加困难,该编译器应当明确告知不应当优化栈金丝雀检查程序。

                      • 在所有项目架构上进行模糊测试。某些漏洞由于自身具体特征的原因仅在其中一种平台上出现。

                      • 确保在模糊测试和测试阶段使用清洁程序。例如,内存清洁器必定会识别出某类漏洞如使用 if 未初始化值。

                      从积极方面看,利用服务器端漏洞时要求进行密码验证,而出于安全考虑,该服务器可能禁止用户配置不受密码保护的验证方法。例如,在 UltraVNC 中就是这种情况。作为攻击防御措施,不应该将客户端连接到位置的 VNC 服务器,管理员应该在使用唯一强密码的服务器上配置验证。

                      该研究发现的CVE 漏洞如下:

                      1、LibVNC

                      CVE-2018-6307

                      CVE-2018-15126

                      CVE-2018-15127

                      CVE-2018-20019

                      CVE-2018-20020

                      CVE-2018-20021

                      CVE-2018-20022

                      CVE-2018-20023

                      CVE-2018-20024

                      CVE-2019-15681

                      2、TightVNC

                      CVE-2019-8287

                      CVE-2019-15678

                      CVE-2019-15679

                      CVE-2019-15680

                      3、TurboVNC

                      CVE-2019-15683

                      4、UltraVNC

                      CVE-2018-15361

                      CVE-2019-8258

                      CVE-2019-8259

                      CVE-2019-8260

                      CVE-2019-8261

                      CVE-2019-8262

                      CVE-2019-8263

                      CVE-2019-8264

                      CVE-2019-8265

                      CVE-2019-8266

                      CVE-2019-8267

                      CVE-2019-8268

                      CVE-2019-8269

                      CVE-2019-8270

                      CVE-2019-8271

                      CVE-2019-8272

                      CVE-2019-8273

                      CVE-2019-8274

                      CVE-2019-8275

                      CVE-2019-8276

                      CVE-2019-8277

                      CVE-2019-8280

                      原文链接

                      https://ics-cert.kaspersky.com/reports/2019/11/22/vnc-vulnerability-research/

                      声明:本文来自代码卫士,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。