EPICS Base 堆溢出,已在 7.0.11 中修复 (CVE-2026-114595)
未经身份验证的 Channel Access 消息可破坏 EPICS Base 7.0.10 及更早版本的内存;该批漏洞已在 7.0.11 中修复,目前没有已知的利用。
TL;DR
- EPICS Base 是支撑加速器和望远镜控制系统的开源框架,其中四个内存安全漏洞让一个未经身份验证的网络对端可以破坏 Input/Output Controller 的内存。最严重的 CVE-2026-114595 评分 CVSS v3.1 9.8(Critical)。CISA 于 2026 年 10 月 27 日发布了公告 ICSA-26-300-01,Cipher Research 同日公开了研究结论。
- EPICS Base 7.0.10 及更早的所有版本都受影响。其中三个漏洞位于 TCP 5064 上服务端的 Channel Access 消息解析,第四个在 TCP 5075 上的经典 pvAccess 连接验证中触发。
- Cipher 在沙箱中演示了堆损坏和进程崩溃,但没有演示代码执行;远程代码执行是 CISA 评估的潜在后果。目前没有已知的利用,截至 2026 年 11 月 3 日,四个 CVE 都不在 CISA 的已知被利用漏洞(KEV)目录中。
- 将所有受影响的部署升级到 EPICS Base 7.0.11,升级前先测试旧的 Channel Access 客户端。「我如何修复?」一节包含向后移植和网络隔离步骤。
我受影响吗?
以下条件全部成立时,您处于暴露状态:
- 您运行基于 EPICS Base 7.0.10 或更早版本构建的 EPICS Input/Output Controller(IOC)或其他服务器。CISA 的公告将 7.0.10 及更早的所有版本列为受影响。
- 攻击者可以访问服务器的协议端口:Channel Access 的 TCP 5064(发现端口 UDP 5064),或经典 pvAccess 的 TCP 5075(发现端口 UDP 5076)。
- 不需要任何凭据。在 Cipher 的测试配置中不需要特权账户,三个 Channel Access 漏洞只需要一条 TCP 连接,写入路径还需要一个通道。
IOC 的访问安全规则不改变这一点。这些规则决定客户端可以读写什么,并不能让畸形消息的解析变得安全。pvAccess 漏洞在连接验证期间、该交换完成之前即可触发。
| 分支 | 受影响版本 | 修复版本 |
|---|---|---|
| EPICS Base,7.0 系列 | 7.0.10 及更早 | 7.0.11 |
| EPICS Base,包括 3.x 在内的旧系列 | CISA「7.0.10 and prior」描述覆盖的所有版本 | 无专门发布版本;向后移植 7.0.11 的修复 |
在每台设施主机上检查您运行的版本:
# In each EPICS Base installation: the generated version header
grep EPICS_VERSION_SHORT <epics-base>/include/epicsVersion.h
# In each IOC application directory: which EPICS Base it builds against
grep -n "EPICS_BASE" configure/RELEASE
# On the IOC host: which processes serve Channel Access and pvAccess
ss -tlnp | grep -E ':5064|:5075'
供应商提供的控制器和束线软件包也可能内置 EPICS Base,请一并清点。正如 Cipher 指出的,一个设施可能通过内部维护的应用运行 EPICS,另一个设施则在供应商设备中随附接收。
我如何修复?
先升级,然后复查让漏洞暴露的协议可达性:
- 将所有受影响的 7.0 系列部署从 EPICS 发布页面 升级到 EPICS Base 7.0.11。维护者声明他们未在旧客户端程序上测试过加固后的 Channel Access 服务器,请在投入生产前充分测试旧客户端。
- 无法迁移到 7.0.11 的旧系列,请向后移植两个上游修复:epics-base pull request 934 和 pvDataCPP pull request 109。epics-base pull request 934 说明,向 2017 年之前的版本移植还需要 commit e430d09。
- 在部署期间将协议端口限制到需要的控制主机。CISA 的建议做法适用:让控制系统脱离互联网,与业务网络隔离,必要的远程访问使用最新版本的 VPN。
- 如果您把 EPICS 打包进产品,请验证您的副本是否包含受影响的 Channel Access 或经典 pvAccess 代码。按照 Cipher 对下游维护者的建议,为您的客户发布按版本的指引或向后移植修复。
封锁端口只是降低暴露,不能替代升级。在修复就位之前,该 IOC 仍在用有漏洞的代码解析合法客户端发来的消息。
根本原因是什么?
Channel Access 服务器在计算消息大小和转换消息时信任头部提供的元素数量和长度。经典 pvAccess 的反序列化器把解码出的元素直接转换为其所在数组声明的类型,而不检查它们是否真的具有该类型。
Channel Access 是 EPICS 最初的客户端-服务器协议。服务端实现 RSRV 把每个请求头部读入一个 caHdrLargeArray 结构,其 m_dataType、m_count 和 m_postsize 字段直接来自网络,随后在 modules/database/src/ioc/rsrv/camessage.c 中据此行动。在 7.0.10 的写入路径中,没有任何代码将这些字段与通道或实际到达的负载做交叉校验:
// epics-base/modules/database/src/ioc/rsrv/camessage.c at R7.0.10 (write_action)
status = caNetConvert (
mp->m_dataType, pPayload, pPayload,
FALSE /* net -> host format */, mp->m_count );
无论通道持有多少元素、请求实际携带多少字节,转换都会从接收缓冲区按 m_dataType 类型消费 m_count 个元素。消息分发循环同样用未经检查的 32 位算术构造大小:
// epics-base/modules/database/src/ioc/rsrv/camessage.c at R7.0.10 (camessage)
msg.m_postsize = ntohl ( pLW[0] );
msg.m_count = ntohl ( pLW[1] );
msgsize = msg.m_postsize + sizeof(*mp) + 2 * sizeof ( *pLW );
按照 Cipher 的分析,四个 CVE 分别是这种信任的一个后果:
- CVE-2026-114595(CVSS v3.1 9.8,CWE-190):写入请求的元素数量与元素大小无上限地相乘,32 位算术溢出,分配的内存小于随后的转换所需。在 AddressSanitizer 下,这产生了攻击者可控字节的堆缓冲区越界写入。
- CVE-2026-114596(CVSS v3.1 8.2,CWE-190):接近 32 位上限的扩展头部负载长度使计算出的消息大小回绕并通过过大检查,随后的通道创建路径把一个终止字节写到可用内存之外。
- CVE-2026-114597(CVSS v3.1 7.5,CWE-130):声明的元素数量超过收到的负载,转换越过接收缓冲区,构成越界读取。
- CVE-2026-114598(CVSS v3.1 7.5,CWE-843):在
pvDataCPP的FieldCreate::deserialize中,结构体数组或联合体数组的描述接受了不同类型的元素,代码按照错误的布局解释它,包括携带指针的字段。
漏洞如何被利用?
不存在公开的概念验证(PoC):Cipher 没有公布其复现负载,上游补丁是每个修复所关闭内容的唯一公开记录。下面的步骤是分析所描述的机制。
- 攻击者向 IOC 的 Channel Access 端口打开一条普通 TCP 连接,发送头部声明一个大元素数量和一个类型的写入请求。
- 元素数量与元素大小通过 32 位算术相乘并回绕,服务器为随后要处理的数据分配了过小的内存。
- 攻击者负载的转换在这块过小的分配中继续进行。在 AddressSanitizer 下,该请求产生了攻击者可控字节的堆缓冲区越界写入,随后进程崩溃。
- 扩展头部变体声明一个接近 32 位上限的负载长度,大小检查回绕,随后的通道创建路径把一个终止字节放到可用内存之外,构成受限的越界写入。
- 读取变体声明的元素多于负载所含;pvAccess 变体在认证完成之前的早期连接验证中,于结构体数组描述里发送一个类型错误的元素。两者都作为越界读取使服务器线程崩溃。
攻击流程是怎样的?
一条未经身份验证的写入请求发往 Channel Access 端口,通过回绕的大小计算破坏 IOC 的堆。
无需凭据"] --> B["写入请求头部:元素数量
经过挑选以让大小
计算溢出"] B --> C["RSRV 将数量与元素大小
相乘,不与通道和
负载做任何
交叉校验"] C --> D["32 位计算回绕:
缓冲区分配过小"] D --> E["转换把攻击者数据
写到缓冲区之外"] E --> F["堆损坏:IOC 崩溃;
CISA 评估存在
代码执行的可能"]
攻击者能做什么?
已演示的影响是内存损坏和拒绝服务,全部由 Cipher 在 AddressSanitizer 或调试器下复现:
- CVE-2026-114595 产生了攻击者可控字节的堆缓冲区越界写入,这是构建远程代码执行的原始类别。CISA 将该漏洞评为 Critical,影响为潜在的代码执行;Cipher 没有构建利用程序,也没有评估损坏在生产构建上的可靠性。
- CVE-2026-114596 是受限的越界写入:在计算决定的偏移处写入一个固定字节,结果是远程触发的崩溃,而不是通用的写入原语。
- CVE-2026-114597 和 CVE-2026-114598 是越界读取。Cipher 确认了崩溃,没有演示向远程客户端泄露内存内容。
让 IOC 崩溃本身就有运行后果。IOC 在更大的装置中承担监视、数据采集和设备控制。正如分析指出的,中断它可能使操作人员或自动化失去观测或控制功能。接下来会发生什么取决于设施的架构:冗余、失效保护和独立的保护联锁决定影响范围。
条件是 TCP 端口的可达性,写入路径还需要一个通道:在 Cipher 的测试配置中不需要特权账户。
修复为何有效?
7.0.11 发布包含 epics-base pull request 934 和 pvDataCPP pull request 109,每一个都准确关闭其漏洞所利用的校验缺口。写入路径现在校验类型、限制元素数量,并将计算出的大小与实际到达的负载比较:
# epics-base/modules/database/src/ioc/rsrv/camessage.c (write_action, PR 934)
- pciu = MPTOPCIU(mp);
+ pciu = MPTOPCIU(mp, client);
if(!pciu){
logBadId(client, mp, pPayload);
return RSRV_ERROR;
}
+
+ if (INVALID_DB_REQ(mp->m_dataType)) {
+ log_header ("bad put data type", client, mp, pPayload, 0);
+ return RSRV_ERROR;
+ }
+ if (mp->m_count > dbChannelFinalElements(pciu->dbch)) {
+ mp->m_count = dbChannelFinalElements(pciu->dbch);
+ }
+
+ size = dbr_size_n (mp->m_dataType, mp->m_count);
+ if (size > mp->m_postsize) {
+ return RSRV_ERROR;
+ }
消息分发循环现在拒绝会让大小算术回绕的扩展长度:
# epics-base/modules/database/src/ioc/rsrv/camessage.c (camessage, PR 934)
msg.m_postsize = ntohl ( pLW[0] );
msg.m_count = ntohl ( pLW[1] );
+ if (msg.m_postsize >= ca_uint32_max - (sizeof(*mp) + 2 * sizeof ( *pLW ))) {
+ if(CASDEBUG>0) {
+ errlogPrintf("Client ext msg size too large 0x%08x\n",
+ (unsigned)msg.m_postsize);
+ }
+ status = RSRV_ERROR;
+ break;
+ }
msgsize = msg.m_postsize + sizeof(*mp) + 2 * sizeof ( *pLW );
pvAccess 的类型混淆通过在转换前校验解码元素的实际类型来关闭,反序列化递归也加了边界:
# pvDataCPP/src/factory/FieldCreateFactory.cpp (FieldCreate::deserialize, PR 109)
- StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
+ StructureConstPtr elementStructure = std::tr1::dynamic_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
+ if(!elementStructure)
+ throw std::invalid_argument("Expected Structure");
pull request 934 将同样的元素数量上限和负载交叉校验应用到读取、事件添加和写通知路径。通道查找现在也拒绝其他客户端创建的标识符,三个 Channel Access 漏洞由一个变更集覆盖。pull request 自身的描述与此一致:在相关的 msgsize、dtype 和 count 头部字段之间做交叉校验,首先避免整数溢出。
我如何检查是否已被入侵?
没有公开的入侵指标,因为既没有公开复现负载也没有攻击流量。一次失败的尝试可能只留下一次崩溃。
- 检查 IOC 可用性记录中协议端口附近无法解释的进程重启或崩溃,包括 IOC 主机上的 core 文件。
- 在防火墙或流量日志中查找在崩溃之前访问 TCP 5064 或 TCP 5075 以及 UDP 5064 和 5076 发现端口的意外来源。
- 确认是否有 IOC 可以从管理、远程访问、科研、访客或桥接网段访问。Cipher 明确将这些列为需要复查的路径。
- 任何已确认的越界事件,其影响在检查之前都应视为未知。没有公开负载,就没有指纹能区分制造崩溃的尝试与真正的利用尝试。
时间线
- 2026-06-09:Causal Security 将四个发现报告给 EPICS 安全渠道,并与 CISA 协调 CVE 分配和下游通知。
- 2026-07-23:Channel Access 加固,即 epics-base pull request 934,在 Cipher 的 Shubham Raj 的机密报告和一份重叠的非机密报告之后合并到 7.0 分支。
- 2026-08-10:pvAccess 类型混淆修复,即 pvDataCPP pull request 109,合并。
- 2026-10-26:base-7.0.11.tar.gz 发布包及其签名从 7.0 分支生成。
- 2026-10-27:EPICS Base 7.0.11 发布,CISA 发布公告 ICSA-26-300-01,Cipher Research 发布其分析。
常见问题
远程代码执行被演示了吗?
没有。CISA 的公告说明最严重的漏洞「may result in memory corruption, denial of service, or potential remote code execution」,而 Cipher 的沙箱产生了攻击者可控字节的堆缓冲区越界写入。Cipher 没有构建利用程序,也没有评估损坏在生产构建上的可靠性。代码执行仍是评估出的可能性,不是演示出的结果。
四个 CVE 中有被在野利用的吗?
没有已知的利用,截至 2026 年 11 月 3 日,四个 CVE 都没有出现在 CISA 的已知被利用漏洞目录中。四个 CVE 记录也不携带 CISA ADP 评估块,因此没有可引用的 SSVC 利用标记。
IOC 访问安全规则能阻止这些攻击吗?
不能。访问规则决定客户端可以读写什么,pvAccess 连接验证协议提供身份验证。Cipher 表示两者都不能替代修复:这些控制不能让畸形消息的解析变得安全,而 pvAccess 漏洞在连接验证期间、该交换完成之前触发。
我们运行的是 EPICS Base 3.15,不是 7.0 系列。受影响吗?
是的。CISA 的公告将 EPICS Base 7.0.10 及更早的所有版本列为受影响。3.15 系列没有任何版本包含这些修复,请向后移植 epics-base pull request 934 和 pvDataCPP pull request 109;前者说明 2017 年之前的版本还需要 commit e430d09。供应商打包的产品需要供应商的向后移植。
升级会破坏旧的 Channel Access 客户端吗?
有可能。7.0.11 发布页面说明维护者没有在旧的客户端程序上测试过加固后的 Channel Access 服务器,并建议设施在生产部署前充分测试。请带着旧客户端清单规划升级。
谁发现了这些漏洞,如何发现的?
Causal Security 的自主安全系统 Cipher 的 Shubham Raj 在一个从未见过的代码库上用 3 小时 49 分钟发现并验证了全部四个漏洞。调查不需要人工介入;唯一的人工步骤是一条授权在隔离沙箱中进行更深入可利用性测试的指令。
用 Ostorlab 发现已暴露的控制系统服务
Ostorlab 的攻击面发现会清点您网段中暴露在互联网上的主机,在规划升级窗口之前找出所有在 Channel Access 或 pvAccess 端口上应答的主机。开始使用 Ostorlab 扫描,了解哪些站点需要优先修复。
参考文献
- CISA 工业控制系统公告 ICSA-26-300-01「EPICS Base」,2026 年 10 月 27 日发布,包含四个 CVE 的描述、CVSS 向量和修复链接:https://www.cisa.gov/news-events/ics-advisories/icsa-26-300-01 (2026 年 11 月 3 日核对)
- Cipher Research,Causal Security,《Inside EPICS Base: Four severe vulnerabilities discovered autonomously in under four hours》,2026 年 10 月 27 日发布,包含逐漏洞机制、端口和披露时间线:https://causalsecurity.com/research/epics-base-security-research (2026 年 11 月 3 日核对)
- CVE-2026-114595 记录,CVSS v3.1 9.8 和 v4.0 9.3:https://www.cve.org/CVERecord?id=CVE-2026-114595 (2026 年 11 月 3 日核对)
- CVE-2026-114596 记录,CVSS v3.1 8.2 和 v4.0 8.8:https://www.cve.org/CVERecord?id=CVE-2026-114596 (2026 年 11 月 3 日核对)
- CVE-2026-114597 记录,CVSS v3.1 7.5 和 v4.0 8.7:https://www.cve.org/CVERecord?id=CVE-2026-114597 (2026 年 11 月 3 日核对)
- CVE-2026-114598 记录,CVSS v3.1 7.5 和 v4.0 8.7:https://www.cve.org/CVERecord?id=CVE-2026-114598 (2026 年 11 月 3 日核对)
- epics-base pull request 934《RSRV message validation》,2026 年 7 月 23 日合并,Channel Access 修复并附有 2017 年前版本的移植说明:https://github.com/epics-base/epics-base/pull/934 (2026 年 11 月 3 日核对)
- pvDataCPP pull request 109,pvAccess 类型校验和递归边界修复,2026 年 8 月 10 日合并:https://github.com/epics-base/pvDataCPP/pull/109 (2026 年 11 月 3 日核对)
- EPICS 7.0.11 发布页面,2026 年 10 月 26 日,包含旧客户端互操作警告和下载链接:https://epics-controls.org/resources-and-support/base/epics-7/7-0-11/ (2026 年 11 月 3 日核对)
- EPICS Base R7.0.11 GitHub 发布,2026 年 10 月 27 日发布:https://github.com/epics-base/epics-base/releases/tag/R7.0.11 (2026 年 11 月 3 日核对)
- 被引用为根本原因的脆弱源码,标签 R7.0.10 的 camessage.c:https://github.com/epics-base/epics-base/blob/R7.0.10/modules/database/src/ioc/rsrv/camessage.c (2026 年 11 月 3 日核对)
- CISA 已知被利用漏洞目录 JSON 数据源,检索四个 CVE 均无匹配(截至 2026 年 11 月 3 日):https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (2026 年 11 月 3 日核对)