针对 Apache Camel 漏洞的可运行概念验证复现程序。在该漏洞中,远程文件消费者轮询远程服务器上的某个目录,并通过将配置的目录与服务器目录列表中报告的文件名拼接来构建每个文件的绝对远程路径,既没有词法规范化,也没有检查结果是否仍位于被轮询的目录内。该路径随后成为检索操作的操作数(始终如此),并且在配置了 delete=true、move、preMove、moveFailed 或 readLock=rename 时,也成为删除或重命名操作的操作数。
列表中的名称不是路由可控的数据——它由远程服务器提供,而 FTP 控制通道没有完整性保护,因此路径上的攻击者可以改写 LIST 响应,被攻陷的服务器或多租户服务器也可以直接发出这样的名称。文档中说明的、默认开启的 jailStartingDirectory 选项并未约束这个远程操作数。
| 运行时 | 目录 | 技术栈 |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-ftp 4.22.0(受影响;修复版本 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-ftp 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。
该应用内嵌了一个故意恶意的 FTP 服务器(使用内存 VFS 的 Apache MINA FtpServer),它在被轮询的目录 /upload 中列出:
normal.txt —— 该目录内的一个合法文件,以及d/../../outside.txt —— 一个精心构造的条目,其名称不是单个路径段。它不以点开头
(因此 Camel 的隐藏文件规则不会捕获它),并且 /upload + d/../../outside.txt 解析为 /outside.txt,
位于被轮询目录之上一级。一个普通的 Camel FTP 消费者轮询 /upload。在受影响的构建上,它会检索两个条目——包括
/outside.txt,一个它本不应触及的文件。在修复后的构建上,它会保留 normal.txt 并跳过逃逸的
条目,同时记录日志 Skipping file as it resolves outside the starting directory: upload/d/../../outside.txt。
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
受影响构建上的预期输出:
What the Camel consumer retrieved:
name=[normal.txt] (inside)
name=[d/../../outside.txt] <<< FILE FROM OUTSIDE THE POLLED DIRECTORY
content: OUTSIDE-SECRET (/outside.txt, a file the consumer should never reach)
Paths the server was asked to read:
upload/normal.txt -> /upload/normal.txt
upload/d/../../outside.txt -> /outside.txt
| 属性 | 值 |
|---|---|
| 组件 | camel-ftp(ftp、ftps、sftp 方案) |
| CWE | CWE-22(对路径名的限制不恰当导致受限目录访问) |
| 严重性 | 高 |
| 攻击向量 | 一个 LIST 条目(由服务器提供,可在未认证的 FTP 控制通道上被改写)不是单一路径段 |
| 影响 | 读取——以及在使用 delete/move/readLock=rename 时,删除或重命名——轮询目录之外的文件,使用端点的凭据 |
| 受影响版本 | 从 4.0.0 到 4.18.5 之前,从 4.19.0 到 4.22.1 之前 |
| 修复版本 | 4.18.5、4.22.1、4.23.0 |
| JIRA | CAMEL-24487 |
| 致谢 | 来自 NSSL、SJTU 的 Dilrevx |
公告:https://camel.apache.org/security/CVE-2026-79983.html
一个能识别分隔符的 GenericFileHelper.isWithinDirectory 重载方法,以及一个 GenericFileConsumer.isWithinStartingDirectory
策略(当启用 jailStartingDirectory 时由 isValidFile 调用),会压缩解析后的路径,并在路径段边界上验证
它仍然解析到轮询目录内部。解析到外部的文件会被跳过并给出警告(因此同一列表中的其他合法条目仍会被处理)。
RemoteFileConsumer 和 SmbConsumer 覆盖了该检查;本地基础实现为空操作,因为本地列表名称始终是
单一路径段。
优先使用 sftp/ftps 而非 ftp,这样列表在传输过程中无法被改写,并验证主机密钥/证书。
使用 filter、antInclude 或 include 约束消费者,只接受单段名称,并避免对列表不完全可信的服务器使用
delete=true/move/preMove/moveFailed/readLock=rename。
在可能的情况下,将服务器账户限制在轮询目录内。
本仓库出于教育和防御目的发布:帮助 Apache Camel 用户理解该漏洞、验证自己是否受影响,并确认升级可以解决该问题。 恶意服务器和“secret”均为无实际作用的本地测试夹具。请勿将本材料用于您不拥有或运营的系统。