GoAhead 中的三个 TLS 漏洞
摘要
FoxIO披露了GoAhead嵌入式Web服务器中三个独立的TLS漏洞:OpenSSL后端未强制执行CRL吊销检查(CVSS 9.1)、LibreSSL旧版验证器可绕过证书链深度限制(CVSS 7.4),以及Mbed TLS后端的DH参数缓冲区错误导致TLS 1.2会话可被解密(CVSS 5.9),影响数亿台IoT、防火墙和工业控制设备,建议升级至6.1.1或更高版本。
暂无内容
查看缓存全文
缓存时间:
2026/10/28 01:51
# 选择你的后端:GoAhead 中的三个 TLS 漏洞 - FoxIO | 网络创新
来源:https://foxio.io/blog/choose-your-backend-three-tls-bugs-in-goahead
## 摘要
GoAhead 被用于数亿台物联网、防火墙、运营技术和军用设备,其中包括 Palo Alto Networks、Comcast、D\-Link、HP、Canon、Honeywell、GE、Oracle、Siemens、Rockwell、Digi、Lockheed Martin、Boeing 等公司的设备。
GoAhead 的 TLS 集成中存在三个相互独立的漏洞,可能导致已吊销的客户端证书仍被接受、加密会话可被观察者还原,或配置的证书链深度限制未得到执行。具体风险取决于设备中构建的 TLS 库和验证设置:
- OpenSSL 兼容后端 \- 严重,CVSS 9\.1 \- CRL 已加载但未强制执行,已吊销的客户端证书会被静默接受。GOAHEAD\-SA\-2026\-0006。
- LibreSSL 旧版验证器 \- 高危,CVSS 7\.4 \- 当要求客户端证书但禁用颁发者检查时,超出深度限制的客户端证书链仍会被接受。这会绕过证书链深度限制。GOAHEAD\-SA\-2026\-0004。
- Mbed TLS \- 中危,CVSS 5\.9 \- 缓冲区长度的一处笔误将 2048 位 DH 模数缩减为一个字节。当客户端接受这些错误参数时,TLS 1\.2 DHE\_RSA 会话可被解密。GOAHEAD\-SA\-2026\-0005。
TLS 构建
GoAhead 版本
必要配置
修复或缓解措施
**OpenSSL 兼容后端**
\>= 3\.4\.5, <= 6\.1\.0
启用 mTLS 并配置 CRL。即使启用了颁发者验证,已吊销的客户端证书仍会被接受。
升级至**6\.1\.1 或更高版本**。
**Mbed TLS 后端**
\>= 4\.0\.2, <= 6\.1\.0
与接受错误 DH 参数的客户端协商使用 TLS 1\.2 DHE\_RSA。
升级至**6\.1\.1 或更高版本**,禁用有限域 DHE 套件,或使用 OpenSSL 后端。
**LibreSSL 旧版验证器**— 3\.2\.x 或 3\.3\.2–3\.3\.6
<= 6\.1\.0
`VERIFY\_PEER=1`且`VERIFY\_ISSUER=0`。超出深度限制的客户端证书链会被接受。
启用`VERIFY\_ISSUER=1`并配置受信任的 CA 证书包,或使用 OpenSSL / LibreSSL 4\.x。
## 背景
GoAhead 是一种用于设备管理的嵌入式 Web 服务器,应用于路由器、交换机、打印机、网关和工业控制设备,已部署在数亿台设备中。
下面的每项发现都只影响其中某一类部署,具体取决于构建方式和配置。
GoAhead 支持两种 TLS 后端:默认使用的 OpenSSL,以及 MbedTLS。OpenSSL 后端也适用于 LibreSSL 等兼容库。
GoAhead 对某些配置采用编译时设置的方式:
\-`ME\_GOAHEAD\_SSL\_VERIFY\_PEER=1`要求提供客户端证书。
\-`ME\_GOAHEAD\_SSL\_AUTHORITY`指向一个包含受信任 CA 的 PEM 证书包。
\-`ME\_GOAHEAD\_SSL\_VERIFY\_ISSUER=1`要求证书链依据该证书包建立颁发者信任。
\-`ME\_GOAHEAD\_SSL\_REVOKE`指向一个采用 PEM 编码的证书吊销列表。
\- OpenSSL 后端将证书链深度限制设置为 10(`VERIFY\_DEPTH`)。
## OpenSSL 兼容构建
GoAhead 的 OpenSSL 后端会将配置的 CRL 加载到证书存储中,却从未启用吊销检查。因此,即使启用了颁发者验证,已吊销的客户端证书仍可完成 mTLS 握手。
CRL 在`sslOpen\(\)`中加载:
OpenSSL 需要通过`X509\_V\_FLAG\_CRL\_CHECK`启用 CRL 检查。将文件加载到存储中并不会设置该标志。如果未启用 CRL 或 OCSP 检查,`check\_revocation\(\)`会在检查吊销状态之前返回成功:
GoAhead 从未设置这两个 CRL 标志中的任何一个。OpenSSL 会在不检查已加载列表的情况下返回成功。应用程序的回调本会通过其`default:`分支拒绝错误 23,即`X509\_V\_ERR\_CERT\_REVOKED`,但验证器从未产生该错误。
在使用 OpenSSL 3\.6\.2 的 GoAhead 6\.1\.0 上,一个已吊销且由 CA 签名的客户端证书在启用颁发者验证的情况下完成了 mTLS 握手。验证回调在整个证书链上均报告错误 0:
`X509\_STORE\_load\_locations\(\)`成功执行,因此启动时不会发出任何警告,提示 CRL 强制执行未启用。
**受影响范围:**使用 OpenSSL 兼容后端且配置了 CRL 的 GoAhead 3\.4\.5 至 6\.1\.0。当设置`VERIFY\_PEER=1`、配置受信任的 CA 证书包并设置`VERIFY\_ISSUER=1`时,安全影响最为明确:先前受信任但已被吊销的身份仍保有访问权限。当禁用颁发者检查时,CRL 缺陷依然存在,但策略本身已经允许未知颁发者。
**修复**:6\.1\.1 现在会在加载 CRL 后进行检查:
## Mbed TLS 构建
GoAhead 的 mbed TLS 后端通过`mbedtls\_ssl\_conf\_dh\_param\_bin\(\)`配置 RFC 3526 中的 2048 位 DH 组。传递给该函数的模数长度取自生成元缓冲区:
长度参数告诉 mbed TLS 应从每个缓冲区读取多少字节。该调用对两个缓冲区都使用了`sizeof\(dhm\_g\)`,尽管`dhm\_g`只有一个字节长。`dhm\_p`的长度应为`sizeof\(dhm\_p\)`,即 256 字节。
因此,mbed TLS 仅读取`dhm\_p`的第一个字节:`0xFF`(255)。其余 255 字节被丢弃。它接受这个值,并在 TLS 1\.2 DHE\_RSA 握手期间将其发送给客户端:
在 ServerKeyExchange 中,`00 01 ff`表示一个值为 255、长度为一个字节的 DH 参数。它本应包含完整的 256 字节值。
这些错误参数使共享秘密仅有八个可能的值,十六进制表示为:`01`、`02`、`04`、`08`、`10`、`20`、`40`和`80`。观察者可以逐一尝试这些候选值,并通过检查能否成功解密捕获的流量来确定正确值。
在随附的 PoC 中,我经过五次尝试就成功复现了共享秘密。它与客户端的秘密值一致,确认可以派生出相同的 TLS 会话密钥来解密 HTTP 交互。
被动观察者可以利用记录的握手和加密应用数据记录,完全在带外解密捕获的会话。
利用此漏洞需要客户端接受错误的 DH 参数。测试中的 OpenSSL 客户端拒绝了这些参数,并报告`DH\_check\_params\_ex: modulus too small`。宽松的客户端,包括未检查最小长度的自定义或嵌入式实现,可以完成一个可被解密的会话。ECDHE 会话和 TLS 1\.3 不受这一已配置的有限域组影响。
**受影响范围:**使用 mbed TLS 后端及 TLS 1\.2 DHE\_RSA 套件,且客户端接受这些参数的 GoAhead 4\.0\.2 至 6\.1\.0。该笔误于 2018 年迁移到二进制参数 API 时引入,并在 2024 年 4 月的 TLS 重构后依然存在。Mbed TLS 4\.x 移除了`TLS\_DHE\_\*`套件,因此其中不存在这条受影响的 DHE 路径。
如果你在环境的 JA4S 日志中看到任何这些套件,则可能受到影响(例如`t120100\_009f\_1ca028f07214`)
你可能需要运行的示例查询(在 Splunk 或其他工具中)如下:
将 0014 替换为上面列出的曲线。
**修复**:6\.1\.1 修复了该笔误
## LibreSSL 构建
简单来说,在受影响的构建上,攻击者可以提交一个超过 GoAhead 限制的证书链,并仍然完成 mTLS 握手。LibreSSL 报告的是颁发者错误,而不是深度错误。当禁用颁发者检查时,GoAhead 会接受该颁发者错误。
GoAhead 6\.1\.0 使用`SSL\_CTX\_set\_verify\_depth\(sslctx, VERIFY\_DEPTH\)`将证书链深度限制设置为 10。其验证回调也会检查深度:
该检查仅在`ok`为真、报告的深度超过限制且尚不存在错误时,才会设置深度错误。随后,回调会对错误进行分类:
禁用颁发者检查时,错误 20,即`UNABLE\_TO\_GET\_ISSUER\_CERT\_LOCALLY`,会被容许。错误 22,即`CERT\_CHAIN\_TOO\_LONG`,则会被拒绝。
LibreSSL 3\.2\.x 和 3\.3\.2–3\.3\.6 默认使用旧版 X\.509 验证器进行对端验证。其证书链构建循环中包含一条 FIXME 注释(这正是最初促使我研究 GoAhead 的原因):
该循环停止构建证书链,却没有记录深度错误。该失败随后以错误 20 的形式传递给 GoAhead。在`VERIFY\_ISSUER=0`的情况下,回调会接受它。
在链接 LibreSSL 3\.3\.6 的 GoAhead 6\.1\.0 上,一个包含 17 张证书、以攻击者控制的自签名 CA 为根的证书链产生了以下回调跟踪:
握手完成后,受客户端证书要求保护的资源返回了 HTTP 200。相同的 GoAhead 源码使用 LibreSSL 4\.3\.1 构建后,在深度 10 处收到错误 22,并拒绝了该证书链。
设置`VERIFY\_ISSUER=0`时,普通自签名证书本来就会被允许。超出深度限制的证书链之所以能够绕过独立的证书链深度限制,是因为验证器报告了一个被容许的颁发者错误。要求受信任客户端 CA 的部署会拒绝该证书链。
**已演示的配置:**GoAhead 6\.1\.0 使用 LibreSSL 旧版验证器,并设置`ME\_GOAHEAD\_SSL\_VERIFY\_PEER=1`及`ME\_GOAHEAD\_SSL\_VERIFY\_ISSUER=0`。启用颁发者信任检查会拒绝错误 20。OpenSSL、BoringSSL、AWS\-LC 和 LibreSSL 4\.x 构建不受这一旧版验证器触发条件的影响。
## 结论
这三项发现均影响 GoAhead 与其 TLS 库的集成。CRL 的强制执行依赖于一个验证标志,DH 参数依赖于传入的缓冲区长度,而证书链深度限制的执行则依赖于验证错误的处理方式。这些缺陷都不会阻止受影响的握手完成。
后端和构建配置决定了哪些缺陷适用。LibreSSL 构建可能同时受到 OpenSSL 兼容后端中 CRL 缺陷和旧版验证器深度问题的影响。mbed TLS 后端使用独立的验证路径,但当客户端接受相关参数时,会受到 DH 截断问题的影响。
要找出你的设备群中受影响的公网服务器,可使用以下与不同后端对应的 JA4Scan\-TLS 指纹:
服务器(GoAhead 6\.1\.x)
JA4Scan\-TLS
OpenSSL 3\.6\.2
03100h0s00sn\_1fe27f6025fb\_d06dc4648d2f\_sr00ss537461
LibreSSL 3\.3\.6
03100h0s00s0\_9d52559f55bc\_c64486648d2f\_sr00sc24603c
LibreSSL 4\.3\.1(不受深度绕过问题影响)
03100h0r00s0\_9d52559f55bc\_c64486206461\_sr00scc98ba1
mbedTLS 3\.6\.6
23100h0s01s0\_d7d3025021f4\_0475c5cede0d\_sr0ss02265cf
在此阅读有关 JA4Scan 的完整博文:
https://foxio.io/blog/introducing-ja4scan-active-server-fingerprinting-for-tls-and-quic
## 概念验证(POC)
复现代码位于https://github.com/FoxIO-LLC/blog_poc/tree/main/chooseyourbackend
## 时间线
\- 2026 年 4 月 22 日 \- 提交 LibreSSL 报告
\- 2026 年 4 月 27 日 \- 提交 MbedTLS 报告
\- 2026 年 4 月 30 日 \- 提交 OpenSSL 报告
\- 2026 年 8 月 2 日 \- GoAhead 6\.1\.1 发布
\- 2026 年 10 月 12 日 \- 安全公告发布
\- 2026 年 10 月 26 日 \- 博文发布
## 参考资料
GOAHEAD\-SA\-2026\-0004 / CVE\-2026\-115884 (https://github.com/embedthis/goahead/security/advisories/GHSA-r392-vqwx-3r4g):mTLS 证书链深度限制绕过
GOAHEAD\-SA\-2026\-0005 (https://github.com/embedthis/goahead/security/advisories/GHSA-fmvx-2xfx-2gq4):MbedTLS DH 参数截断
GOAHEAD\-SA\-2026\-0006 / CVE\-2026\-115881 (https://github.com/embedthis/goahead/security/advisories/GHSA-5m75-xq69-c3c5):OpenSSL CRL 检查未启用
GoAhead SSL 文档 (https://www.embedthis.com/goahead/doc/users/ssl.html)
OpenSSL 验证标志 (https://docs.openssl.org/3.6/man3/X509_VERIFY_PARAM_set_flags/)
OpenSSL (https://docs.openssl.org/3.6/man3/X509_STORE_add_cert/)`X509\_STORE\_set\_flags\(3\)`
RFC 3526 \- MODP Diffie\-Hellman 组 (https://datatracker.ietf.org/doc/html/rfc3526)
相似文章
Ars Technica
一个评分 9.5/10 的严重 UEFI 固件漏洞(CVE-2026-97631)出现在几乎所有服务器厂商使用的 TianoCore EDK2 代码库的 ICMP 组件中,可在 Secure Boot 生效前执行代码,且补丁已提前泄露。
X AI KOLs Following
不到24小时内接连爆出四大网络安全事件:PHP隐藏14年的高危远程代码执行漏洞(由OpenAI牵头用AI发现并已发布补丁)、Node.js一口气修复10个漏洞、印度证书机构eMudhra因私钥生成过弱被破解导致HTTPS信任链受威胁,以及云平台Railway遭入侵导致客户API密钥可能全部泄露。
X AI KOLs
OpenAI 的红队演练发现 Brotli 压缩库存在未认证远程代码执行漏洞,影响 Node.js、Bun、Envoy 等广泛部署的软件;相关修复已通过 CVE 和下游安全更新发布。
Ars Technica
研究人员发现由印度 CA eMudra 签发的 8 个 TLS 证书的私钥强度极其薄弱(熵值仅为 3-8 位,而非预期的 384 位),引发互联网全球范围内的广泛警觉,被比作当年的 Heartbleed 危机。
Lobsters Hottest
Node.js 发布 2026 年 10 月安全更新,覆盖 26.x、24.x、22.x 版本线,修复了包括 Brotli 解码器远程代码执行和 TLS 证书主机名绕过在内的多个高危漏洞。