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

深度解析

深度解析

FreeRDP RDP 中间人攻击,已修复于 3.32.2(CVE-2026-121392)

FreeRDP 在 3.32.2 之前依赖两条手写的身份检查接受服务器证书,持有受信任 CA 证书的中间人可拦截 RDP 会话;请立即更新。

TL;DR

  • FreeRDP 的客户端 TLS 身份检查会接受 Common Name 匹配但 Subject Alternative Names 不匹配的证书,并将 IP 字面量目标与 DNS 名称进行比对。持有客户端信任的 CA 所签发证书的中间人,可以拦截 RDP 会话。
  • 根据 CVE 记录,3.32.2 之前的每个 FreeRDP 版本都受影响。2026 年 7 月描述这些情况的公告声称 3.29.0 已修复,但其中三个情况有两个从未被修复。
  • VulnCheck 的 CVE 记录将该漏洞评为 CVSS v4.0 9.1 Critical,在 CVSS v3.1 上为 7.4 High。尚无利用报告,且截至 2026 年 11 月 4 日,该 CVE 未列入 CISA 的 Known Exploited Vulnerabilities(KEV)目录。
  • 立即更新到 FreeRDP 3.32.2 或更高版本。没有已记录的配置类临时方案;内嵌 FreeRDP 的产品请参见“如何修复?”。

您是否受影响?

以下条件全部成立时,您处于暴露之中:

  • 您运行基于 FreeRDP 的客户端,或内嵌 FreeRDP 的产品,版本低于 3.32.2。CVE 记录将自第一个版本起的每个版本都标记为受影响。
  • 攻击者能够拦截或重定向 RDP TCP 连接,并能出示一张链到客户端已信任 CA 的证书。公告列出的场景包括:错误签发的公共 CA、被入侵或伪造的私有 CA,或其他证书信任链异常。
  • 客户端验证服务器证书。原始披露使用 AutoAcceptCertificate = FALSE、AutoDenyCertificate = TRUE 和 AuthenticationLevel = 2 复现了这些缺陷。

无法获得受信任证书的攻击者不能从该缺陷中受益。该缺陷削弱的是受信任 CA 场景下的服务器身份验证;它并不创造信任。

版本 受影响 修复版本
3.32.1 及所有更早版本 是,在默认身份检查中 3.32.2,2026-10-12 发布
3.32.2 及更高,包括 3.33.0 否 继续保持更新

3.32.2 和 3.33.0 的新 IP 检查中有一个已知缺陷,但它以拒绝方式失败:它拒绝有效匹配,而不是接受错误匹配(参见“修复为什么有效?”)。

检查您运行的环境:

# The FreeRDP 3 client front-ends all print the version
xfreerdp3 --version

# Debian-family package installs
dpkg -l | grep freerdp

# Library copies, including those bundled inside other products
ldconfig -p | grep libfreerdp

内嵌 FreeRDP 的产品需要其自身的更新;产品报告的版本才是要与公告对照的版本。

如何修复?

  1. 更新到 FreeRDP 3.32.2 或更高版本。修复提交进入了 2026 年 10 月 12 日发布的 3.32.2,之后的每个版本都携带它们。
  2. 当供应商发布修复后的库时,更新内嵌 FreeRDP 的产品。CVE 记录的受影响范围从第一个版本开始,因此更旧的内嵌副本也在范围内。
  3. 如果会话可能经过了持有客户端信任证书的拦截者,请将其视为已被入侵。这样的攻击者能看到屏幕内容、击键和剪贴板,并能注入输入,因此请轮换该会话中使用过的每个凭据,并审查会话中执行过的操作。该缺陷不会给攻击者带来这种网络位置;它让已经处于该位置的攻击者能够在会话内操作。

没有已记录的配置类临时方案。发现修复不完整的后续公告没有提出任何缓解措施。3.32.2 实现的正是该公告建议的修复:只有在不存在 DNS SAN 时才考虑 Common Name,IP 目标只与 iPAddress SAN 条目比对。FreeRDP 自己编写了这段逻辑,而没有调用 OpenSSL 的 X509_check_host() 和 X509_check_ip_asc();据该公告,这两个函数应用的是相同的规则。

根本原因是什么?

FreeRDP 执行自己的 Common Name 和 DNS SAN 字符串比对,而不是使用 OpenSSL 的长度感知身份验证 API。3.32.1 标签处 libfreerdp/crypto/tls.c 第 1859 至 1879 行的易受攻击代码块:

/* compare against common name */

if (common_name)
{
    if (tls_match_hostname(common_name, common_name_length, hostname))
        hostname_match = TRUE;
}

/* compare against alternative names */

if (dns_names)
{
    for (size_t index = 0; index < dns_names_count; index++)
    {
        if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
        {
            hostname_match = TRUE;
            break;
        }
    }
}

该代码块的两个特性破坏了服务器身份验证:

  • Common Name 检查和 DNS SAN 检查是无条件的 OR。RFC 6125 第 6.4.4 节要求相反:当证书携带任何 dNSName SAN 条目时,Common Name 无关紧要。一张 CN=rdp01.corp.example、SAN 列表为 DNS:files.corp.example 等不匹配名称的证书,在连接 rdp01.corp.example 时仍然会通过。
  • x509_utils_get_dns_names() 只请求 GEN_DNS 条目。代码在任何地方都不会读取 iPAddress SAN 条目。因此当 RDP 目标是 IP 字面量时,FreeRDP 将该 IP 作为普通字符串与 CN 和 DNS SAN 条目比对。

2026 年 7 月的一份公告 GHSA-43hh-p3vw-hfx3 记录了三个身份检查弱点,并声明 3.29.0 已修复它们。其修复集只关闭了第一种情况,即嵌入 NUL 截断。Common Name 和 IP 字面量这两种情况从 3.29.0 标签起保持逐字节相同,GHSA-jq25-3374-4262 在 2026 年 10 月记录了这一残留缺口。

如何被利用?

  1. 攻击者获得拦截或重定向受害者 RDP 连接的位置。攻击者还需要一张链到客户端信任 CA 的证书,其 Common Name 为目标主机名,或其 DNS SAN 以文本形式包含目标 IP。
  2. 受害者的 FreeRDP 客户端连接,并对攻击者的证书运行 tls_verify_certificate()。链和有效性检查通过,因为该证书确实由受信任的 CA 签发。
  3. Common Name 分支在 SAN 条目不匹配的情况下仍设置 hostname_match = TRUE,或者 IP 字面量目标匹配了某个 DNS SAN 字符串。客户端将该证书接受为服务器的身份。
  4. 攻击者的端点随后承载 RDP 会话:屏幕内容、击键、剪贴板和输入注入,即后续公告的影响描述。

除两份公告中的复现说明外,没有公开的概念验证。原始公告将一个本地测试 CA 安装到隔离的 FreeRDP 证书存储中,在 FreeRDP 的 TLS 握手路径上复现了全部三种情况。后续报告则在已验证证书链的证书上直接调用未修改的 tls_verify_certificate(),没有执行完整的网络握手。

攻击如何展开?

持有受信任证书的中间人提供 RDP 会话,而手写的身份检查接受了不匹配的证书。

flowchart LR A["中间人持有一张
受信任 CA 的证书"] --> B["受害者连接到
RDP 服务器"] B --> C["对攻击者的证书
运行 tls_verify_certificate"] C --> D["CN 匹配,SAN 条目
不匹配:无条件 OR"] D --> E["IP 目标从未读取任何
iPAddress SAN 条目"] E --> F["客户端接受
攻击者的身份"] F --> G["会话流量:屏幕、
击键、剪贴板"]

攻击者能做什么?

攻击者完整拦截 RDP 会话:屏幕内容、击键、剪贴板和输入注入,依据后续公告的影响声明。两份公告都未主张代码执行或直接的凭据提取,原始公告也未主张内存损坏。

攻击首先需要网络位置和受信任证书。签发者不受客户端信任的证书会在身份比对之前就未通过链检查。独立于这条路径对证书进行固定或手动验证的客户端,不在所描述的场景之内。

修复为什么有效?

3.32.2 中的两个提交替换了这两种情况下的手写比对。提交 1a23b21c37“do not check common name if there are DNS SAN”将 Common Name 比较移到 else if 之后:

        common_name = freerdp_certificate_get_common_name(cert, &common_name_length);
        dns_names = freerdp_certificate_get_dns_names(cert, &dns_names_count, &dns_names_lengths);
-
-       /* compare against common name */
-
-       if (common_name)
-       {
-           if (tls_match_hostname(common_name, common_name_length, hostname))
-               hostname_match = TRUE;
-       }
-
        /* compare against alternative names */
-
        if (dns_names)
        {
            for (size_t index = 0; index < dns_names_count; index++)
@@
            }
        }
+       /* compare against common name */
+       else if (common_name)
+       {
+           if (tls_match_hostname(common_name, common_name_length, hostname))
+               hostname_match = TRUE;
+       }

Common Name 现在只在证书完全没有 DNS SAN 条目时才被参考,这正是 RFC 6125 第 6.4.4 节的规则。

提交 350539ec9a“add IP SAN checks”添加了 iPAddress 提取路径。当连接目标解析为 IP 时,循环通过感知二进制的比较将其与证书的 iPAddress SAN 条目比对,绝不会回退到 DNS 字符串比对。

该修复对报告的两个情况是完整的。两个提交重写的代码块包含了项目中对 tls_match_hostname() 的全部调用。原始公告的第三种情况,即嵌入 NUL 截断,已在 3.29.0 中修复。

新的 IP 路径中还剩一个缺陷,但它以拒绝的方式失败。在 3.32.2 和 3.33.0 中,辅助函数 utils_compare_ip_strings() 检查了错误的 inet_pton() 返回值,因此会拒绝所有有效地址。所以 IP 字面量目标永远不会匹配 iPAddress SAN 条目,客户端会转入 known-hosts 检查或用户提示。提交 f5e8a54fb2 在 2026 年 11 月 3 日、3.33.0 发布之后修正了这一检查。

如何检查是否被入侵?

没有发布任何指标,且两份公告都没有报告利用。对客户端而言,一次成功的拦截看起来就像普通的 TLS 会话。

客户端不会留下攻击记录。当证书链受信任且名称匹配时,tls_verify_certificate() 接受证书时既不读取也不更新 FreeRDP 的 known-hosts 存储,因此攻击者的证书不会在其中留下条目。服务器上的 RDP 连接日志是更好的线索:来自意外源地址的会话值得检查,但并不能证明发生了拦截。

时间线

  • 2026-07-15:GHSA-43hh-p3vw-hfx3 发布,记录三个身份检查弱点并声明 3.29.0 已修复它们。
  • 2026-10-07:针对残留情况的两个修复提交由 Armin Novak 编写。
  • 2026-10-12:FreeRDP 3.32.2 携带修复发布,是更广泛强化版本的一部分。
  • 2026-10-19:GHSA-jq25-3374-4262 发布,记录 3 个情况中有 2 个从未在 3.29.0 中修复。
  • 2026-11-03:VulnCheck 发布 CVE-2026-121392,CVSS v4.0 评分为 9.1 Critical。

声称 3.29.0 已修复的公告比真正的修复早了 84 天,而 CVE 记录在发布后 22 天才出现。
图 1:从声称已修复的 7 月公告到 11 月的 CVE 记录。来源:FreeRDP 公告与发布、VulnCheck CVE 记录,2026 年 11 月 4 日查阅

公告说 3.29.0 关闭了这些情况。修复提交在该公告 84 天后才出现,包含它们的版本在 89 天后才发布。

FAQ

为什么该漏洞同时被评为 Critical 和 High?

这两个评级来自对相同事实应用的两个 CVSS 版本。发布该记录的 CVE 编号授权机构(CNA)VulnCheck 将其评为 CVSS v4.0 9.1 Critical,向量为 CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N。VulnCheck 和 FreeRDP 自己的公告都将其评为 CVSS v3.1 7.4 High,向量为 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N。

这会影响 FreeRDP 服务器或代理吗?

该缺陷位于客户端的服务器身份验证中,即 tls_verify_certificate()。3.32.2 的发布说明在同一批次中还列出了另外 44 份公告,这些修复针对恶意的客户端和服务器消息强化了代码。

原始公告错了吗?

其修复版本字段写的是 3.29.0。后续调查显示,3.29.0 的修复集只关闭了嵌入 NUL 的情况,而另外两个情况从该标签起保持逐字节相同。该字段对已记录的 3 个情况中的 2 个是不准确的。

谁报告了这些缺陷?

根据该公告,原始的三情况公告由电子科技大学(UESTC)的 Bin Luo(GitHub 用户 1121984919)报告。记录修复不完整的后续报告没有点名报告者;它披露了在报告者的指导下将 Claude 作为工具使用,报告者在提交前重新验证了每一个引用的提交和行。

更新到 3.33.0 也能修复吗?

是的。修复进入了 3.32.2,而 2026 年 11 月 2 日发布的 3.33.0 携带它们。3.32.2 是最低要求。

在拦截者之前找到您资产中的 FreeRDP 副本

低于 3.32.2 的每个 FreeRDP 构建都在受影响范围内,包括嵌入产品的副本。Ostorlab 的 SCA 和 SBOM 扫描会对您的仓库和镜像中的依赖进行盘点,让您知道哪些组件和产品携带受影响的 FreeRDP。

参考资料

  • CVE-2026-121392,VulnCheck 的 CVE 记录,含两个 CVSS 向量:https://www.cve.org/CVERecord?id=CVE-2026-121392(2026 年 11 月 4 日查阅)
  • VulnCheck 公告,“FreeRDP before 3.32.2 Certificate Identity Validation Bypass via tls_verify_certificate”:https://www.vulncheck.com/advisories/freerdp-before-3.32.2-certificate-identity-validation-bypass-via-tls-verify-certificate(2026 年 11 月 4 日查阅)
  • GHSA-jq25-3374-4262,FreeRDP 公告,“Incomplete fix for GHSA-43hh-p3vw-hfx3”:https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-jq25-3374-4262(2026 年 11 月 4 日查阅)
  • GHSA-43hh-p3vw-hfx3,FreeRDP 公告,“TLS certificate identity validation accepts malformed and non-authoritative identities”:https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-43hh-p3vw-hfx3(2026 年 11 月 4 日查阅)
  • 修复提交 1a23b21c37,“[crypto,tls] do not check common name if there are DNS SAN”:https://github.com/FreeRDP/FreeRDP/commit/1a23b21c37(2026 年 11 月 4 日查阅)
  • 修复提交 350539ec9a,“[crypto,tls] add IP SAN checks”:https://github.com/FreeRDP/FreeRDP/commit/350539ec9a(2026 年 11 月 4 日查阅)
  • 后续提交 f5e8a54fb2,“[core,utils] fix return check for inet_pton”:https://github.com/FreeRDP/FreeRDP/commit/f5e8a54fb2(2026 年 11 月 4 日查阅)
  • FreeRDP 3.32.2 发布说明:https://github.com/FreeRDP/FreeRDP/releases/tag/3.32.2(2026 年 11 月 4 日查阅)
  • 易受攻击源码,3.32.1 标签处的 libfreerdp/crypto/tls.c:https://raw.githubusercontent.com/FreeRDP/FreeRDP/3.32.1/libfreerdp/crypto/tls.c(2026 年 11 月 4 日查阅)
  • CISA 的 Known Exploited Vulnerabilities 目录,JSON 数据源,检索 CVE-2026-121392:https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json(2026 年 11 月 4 日查阅)