针对 Apache Camel 漏洞的可运行概念验证复现程序,该漏洞中 DoclingProducer 通过检查 String 消息体的前缀来决定其含义:
http:// 或 https:// 开头的 body 会被作为要获取的远程 URL 交给 Docling(SSRF),并且/ 开头(或包含反斜杠)的 body 会从本地文件系统读取(文件泄露)。该模式是隐式选择的,没有任何端点选项可以固定单一解释,并且——与 Camel 的 header 命名空间不同——消息体永远不会被 HeaderFilterStrategy 过滤。因此,一个本意是“转换 body 中到达的任何文本”的路由,只要攻击者控制的文本以这些前缀之一开头,就会悄然变成远程资源获取器或本地文件读取器。
| 运行时 | 目录 | 技术栈 | 展示内容 |
|---|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-docling 4.22.0(受影响;修复版本 4.22.1) | SSRF 和文件泄露,以及修复后构建的对照 |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-docling 3.29.0(Camel 4.15.0,受影响) | 仅文件泄露(见注释) |
版本覆盖范围。 本地文件泄露 sink 自 camel-docling 在 4.15.0 中引入以来就存在;远程 URL sink 是在 4.16.0 中随 docling-serve 支持添加的。最新的 Camel Quarkus(3.29.0)捆绑的是 Camel 4.15.0,因此其模块仅演示文件泄露。修复随 Camel 4.18.5 / 4.22.1 / 4.23.0 发布;Spring Boot 模块同时运行受影响构建(4.22.0)和修复后构建(4.22.1),因此它也演示了修补后的行为。目前尚无已发布的 Camel Quarkus 捆绑修复后的 Camel。
两个复现程序都不需要真实的 Docling 安装:一个极小的伪造 docling CLI(fake-docling/docling)代替该二进制文件,并让真实二进制文件在收到生产者提供的输入时会做什么变得可见——获取 URL,或读取文件。它是良性的:它只回显被告知要处理的内容,并记录自身的调用。该 CVE 的关键在于,攻击者提供的 body 竟然能到达该参数,且无需任何显式启用。
Spring Boot 应用还在 127.0.0.1:9099 上运行一个仅限内部的 HTTP 端点(仅发布 8080 端口,因此外部客户端无法直接访问 9099)以及一个本地机密文件。攻击者只发送文本:
http://127.0.0.1:9099/internal-secret → 服务端的 docling 调用会获取该内部端点,其机密被返回给调用者。/tmp/cve-2026-78163-secret.txt → 本地文件被读取并返回。在受影响的构建上,两者均成功;在修复后的构建上,两者均被拒绝,并抛出 IllegalArgumentException,其中指明启用它们所需的选项(allowUrlSource / allowFilePathSource),且 docling 永远不会被调用。
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
在受影响的 Spring Boot 构建上预期输出:
[1] SSRF — sending body = http://127.0.0.1:9099/internal-secret
>>> PROVEN SSRF: the server-side docling invocation fetched the attacker-controlled internal URL.
>>> internal victim saw: [GET /internal-secret]
>>> content returned to the caller:
| INTERNAL-SECRET-DATA (only reachable from inside the deployment)
[2] File disclosure — sending body = /tmp/cve-2026-78163-secret.txt
>>> PROVEN file disclosure: the attacker-named local file was read and returned.
| TOP-SECRET-FILE-CONTENT (local file an attacker should not be able to read)
| 属性 | 值 |
|---|---|
| 组件 | camel-docling(camel-docling-starter / camel-quarkus-docling) |
| CWE | CWE-918(SSRF)、CWE-22(路径遍历)、CWE-200(信息泄露) |
| 严重程度 | 中危 |
| 攻击向量 | 一个 String 消息体被转发到 docling 端点,其前缀会选择 URL 获取或文件读取接收器;该消息体不受 HeaderFilterStrategy 约束 |
| 影响 | 服务端获取攻击者选定的 URL(内部服务)以及泄露本地文件 |
| 受影响版本 | 从 4.15.0 起至 4.18.5 之前,从 4.19.0 起至 4.22.1 之前(文件泄露自 4.15.0 起;URL 接收器自 4.16.0 起) |
| 修复版本 | 4.18.5、4.22.1、4.23.0 |
| JIRA | CAMEL-24422 |
| 致谢 | Li Zhiyao(北京邮电大学) |
公告:https://camel.apache.org/security/CVE-2026-78163.html
现在,String 消息体默认被视为文档本身。两种位置读取方式改为通过新的端点选项 allowUrlSource 和 allowFilePathSource 选择启用(两者默认均为 false);否则,看起来像 URL 或路径的消息体会被拒绝,并抛出 IllegalArgumentException,其中指明可启用该行为的选项。此外,新增的 inputBaseDirectory 选项将本地输入路径限制在配置的目录内。类型化消息体(File、byte[]、InputStream)和 CamelDoclingInputFilePath 头本身已表明其含义,因此不受此限制(但仍受 inputBaseDirectory 约束)。
不要将外部来源的消息体路由到 docling 端点;请通过类型化消息体(File、byte[]、InputStream)或 CamelDoclingInputFilePath 头传递文档,这样消息体就永远不会受到前缀解释的影响。
本仓库出于教育和防御目的发布:帮助 Apache Camel 用户理解该漏洞、验证自身是否受影响,并确认升级可以解决该问题。伪造的 docling CLI 和“机密”均为无实际作用的本地测试夹具。请勿将本材料用于您不拥有或运营的系统。