针对 Apache Camel 漏洞的可运行概念验证复现程序。在该漏洞中,camel-fop 的 FopProducer 在仅设置 FEATURE_SECURE_PROCESSING 的情况下创建其 javax.xml.transform.TransformerFactory,随后对 XSL-FO 消息体执行恒等变换。在 JDK 内置的转换器上,仅该特性本身就会清空 accessExternalDTD/accessExternalStylesheet 限制,因此外部资源会被拒绝。但当类路径上存在第三方 JAXP TransformerFactory(例如 Saxon-HE)时——例如因为应用还使用了 camel-xslt-saxon 或 camel-saxon——TransformerFactory.newInstance() 会返回该实现,而仅靠 FEATURE_SECURE_PROCESSING 并不能限制其对外部资源的访问。此时,在 XSL-FO 消息体中声明的带外部子集的 DOCTYPE 会在消息体被转换时被解析,因此外部发送者的文档可以读取 Camel 进程可读的文件,或使其向文档指定的主机发起请求(CWE-611)。
| 运行时 | 目录 | 技术栈 |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-fop 4.22.0(受影响;修复版本 4.22.1)+ Saxon-HE 13.0 |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.39.0 + camel-quarkus-fop(Camel 4.22.0,受影响;修复对照 CQ 3.40.0 / Camel 4.22.1)+ Saxon-HE 13.0 |
两个模块都针对真实的 FopProducer 演示了受影响以及修复后的行为。两个模块的类路径上都存在 Saxon-HE——这是该缺陷的前提条件;使用 JDK 转换器的默认部署在修复前后均不受影响。
验证端点 /exploit/attack 会启动一个进程内 HTTP 回调,并向 fop:pdf 发送一个 XSL-FO 文档,该文档的 DOCTYPE 声明了一个指向该回调的外部 DTD:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fo:root SYSTEM "http://localhost:<port>/external.dtd">
<fo:root …>…Hello…</fo:root>
oracle 就是回调是否被请求——这是外部资源确实被获取的确定性证据:
TransformerFactory.newInstance() 返回 Saxon,而 Saxon 在仅启用安全处理的情况下仍会获取外部 DTD——回调被触发(同一机制可读取 file:// URL)。ACCESS_EXTERNAL_DTD 被设置为 "",因此 Saxon 拒绝外部 DTD;回调永远不会被触发。# Camel Spring Boot
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: callback hit = true; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -Djava.awt.headless=true -jar target/cve-2026-91858-fop-xxe-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: callback hit = false; >>> Not exploited
# Camel Quarkus
cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected (Camel 4.22.0): callback hit = true
docker compose down
# Patched control: CQ 3.40.0 ships Camel 4.22.1
mvn clean package -Dcamel-quarkus.version=3.40.0 -Dquarkus.platform.version=3.40.0
java -Djava.awt.headless=true -jar target/quarkus-app/quarkus-run.jar &
curl -s http://localhost:8080/exploit/attack # fixed: callback hit = false
| 属性 | 值 |
|---|---|
| 组件 | camel-fop(FopProducer) |
| CWE | CWE-611(XML 外部实体引用限制不当) |
| 严重程度 | 中危 |
| 攻击向量 | 外部发送者的 XSL-FO 到达 fop: 生产者,且该部署的类路径上同时存在第三方 JAXP TransformerFactory(例如 Saxon-HE) |
| 影响 | 读取 Camel 进程可读的本地文件;向文档指定的内部主机发起 SSRF |
| 受影响版本 | 从 4.0.0 起至 4.18.5 之前,从 4.19.0 起至 4.22.1 之前(仅当存在非 JDK 的 TransformerFactory 时) |
| 修复版本 | 4.18.5、4.22.1、4.23.0 |
| JIRA | CAMEL-24605 |
| 致谢 | Claude Security Scan Tool |
公告:https://camel.apache.org/security/CVE-2026-91858.html
Quarkus 受影响模块基于 CQ 3.39.0(Camel 4.22.0)构建。修复后的对照模块为 CQ 3.40.0(Camel 4.22.1)。 两个模块均添加了 Saxon-HE 13.0,用以模拟同时使用 camel-xslt-saxon/camel-saxon 的应用程序; 若不存在非 JDK 的 TransformerFactory,则该缺陷不可达。
FopProducer 现在还会在其创建的 TransformerFactory 上将
XMLConstants.ACCESS_EXTERNAL_DTD 和 XMLConstants.ACCESS_EXTERNAL_STYLESHEET 设置为空字符串(此外还设置了
FEATURE_SECURE_PROCESSING),与 XmlConverter 所使用的安全 XML 处理配置保持一致。因此,在任何遵循这些属性的
JAXP 实现(包括 Saxon-HE)上,外部 DTD 和样式表访问都会被拒绝。
不要将不受信任的 XSL-FO 发送给 fop: 生产者,或者从类路径中移除替代的 JAXP TransformerFactory(例如
Saxon-HE),以便使用 JDK 转换器——它在安全处理模式下已经拒绝外部 DTD。
本仓库出于教育和防御目的发布:帮助 Apache Camel 用户理解该漏洞、验证自身是否受影响,并确认升级可以解决该问题。 外部 DTD 指向 localhost 上的进程内回调;不会联系复现程序之外的任何内容,也不会读取任何敏感文件。请勿将本材料 用于您不拥有或运营的系统。