
CVE-2026-88789에 대한 실행 가능한 개념 증명 재현기로, XSLT TransformerFactory를 통해 Apache Camel Quarkus camel-quarkus-support-xalan에서 XXE 및 SSRF를 시연합니다.
TransformerFactory가 JAXP 외부 접근 제한을 무력화함XSLT 지원 확장(camel-quarkus-support-xalan)이 자체적인 Xalan 기반 TransformerFactory를 xslt 컴포넌트에 제공하고 이를 JAXP 기본값으로 등록하는 Apache Camel Quarkus 취약점에 대한 실행 가능한 개념 증명 재현 코드입니다. Xalan-J 2.7.x는 JAXP 1.5보다 먼저 나왔으며 javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD 또는 ACCESS_EXTERNAL_STYLESHEET를 준수할 수 없습니다 — 두 속성 모두에 대해 setAttribute()가 IllegalArgumentException을 던집니다 — 따라서 Apache Camel이 생성하는 TransformerFactory에 적용하는 외부 접근 제한이 전혀 적용되지 않았습니다.
| 런타임 | 디렉터리 | 스택 |
|---|---|---|
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.36.0 (Quarkus 3.36.0, Camel 4.20.0) |
Camel Quarkus 전용입니다. 취약한 코드는 Camel 컴포넌트가 아니라 Camel Quarkus 확장입니다. 일반 Camel과 Camel Spring Boot는 두 속성을 모두 준수하는 JDK의
TransformerFactory를 사용하므로 재현할 것이 없습니다 — 따라서 이 저장소에는camel-spring-boot/변형이 없습니다.
변환되는 XML 문서를 제공하는 공격자는 해당 문서의 외부 엔티티 선언을 통해 로컬 파일을 읽거나 내부 네트워크 위치에 접근할 수 있습니다.
cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
영향을 받는 빌드에서의 예상 출력 (요약 — 드라이버는 여섯 개의 프로브를 실행합니다,
camel-quarkus/README.md 참조):
1) xslt endpoint, body is a StreamSource, external entity -> file:///tmp/cve-2026-88789-secrets/db-password.txt
transformation result: [db.password=LOCAL-FILE-s3cr3t-99]
local file contents in the output: true
2) xslt endpoint, body is a StreamSource, external entity -> http://127.0.0.1:8080/internal/secret
transformation result: [INTERNAL-SECRET-s3cr3t-42]
internal endpoint response in the output: true
4) CONTROL - same document as a String body (Camel converts it to a SAXSource itself)
transformation result: []
local file contents in the output: false
5) TransformerFactory.newInstance() anywhere in the application
factory: org.apache.camel.quarkus.support.xalan.XalanTransformerFactory
setAttribute(ACCESS_EXTERNAL_DTD, ""): REFUSED, IllegalArgumentException: ...
identity transform of the same document: [... <data>db.password=LOCAL-FILE-s3cr3t-99</data> ...]
Requests the XML parser made to internal endpoints on its own: [GET /internal/secret, GET /internal/leak.dtd]
>>> PROVEN: ...
Camel Quarkus 3.40.0에 대해서도 검증되었습니다: 모든 유출 프로브가 조용해지고, 내부 엔드포인트는 요청을 전혀 받지 않으며, 드라이버는 NOT reproduced를 출력합니다.
xslt 컴포넌트 경로에서, 이미 javax.xml.transform.Source로 변환기에 도달하는 본문만 영향을 받습니다. 다른 타입의 본문 — String, byte[], InputStream — 은 Apache Camel이 외부 엔티티와 외부 DTD 로딩이 비활성화된 SAXSource로 변환하므로 영향을 받지 않습니다. 재현 코드의 프로브 4는 안전하지 않은 경로와 나란히 있는 안전한 경로입니다.
팩토리가 JAXP 기본값으로도 등록되기 때문에 (지원 확장은 META-INF/services/javax.xml.transform.TransformerFactory를 제공합니다), TransformerFactory.newInstance()를 통해 팩토리를 얻는 애플리케이션의 다른 코드는 오류 없이 동일한 제한을 잃습니다. 이것이 권고문이 자체적으로 아무것도 변환하지 않는 확장들을 나열하는 이유입니다:
| 확장 | 노출 |
|---|---|
camel-quarkus-xslt | xslt 컴포넌트 경로 및 JAXP 기본값 |
camel-quarkus-xslt-saxon | JAXP 기본값 |
camel-quarkus-tika | JAXP 기본값 |
camel-quarkus-xmlsecurity | JAXP 기본값 |
| 속성 | 값 |
|---|---|
| 컴포넌트 | camel-quarkus-support-xalan (XSLT 지원 확장) |
| CWE | CWE-611 (XML 외부 엔티티 참조의 부적절한 제한) |
| 심각도 | 높음 |
| 공격 벡터 | 변환되는 XML 문서에 선언된 외부 엔티티 또는 외부 DTD로, 본문이 이미 javax.xml.transform.Source로 xslt 엔드포인트에 도달하는 경우 |
| 영향 | 로컬 파일 읽기; 내부 네트워크 위치에 요청 발행 (SSRF) |
| 영향받는 버전 | 3.2.0부터 3.33.3 이전, 3.34.0부터 3.40.0 이전 |
| 수정된 버전 | 3.33.3 (LTS 스트림), 3.40.0 |
| GitHub 이슈 | apache/camel-quarkus#9115 |
| 크레딧 | Claude Security Tool을 사용한 내부 분석으로 발견 |
권고문: https://camel.apache.org/security/CVE-2026-88789.html
XalanTransformerFactory는 이제 Xalan이 준수할 수 없는 속성에 의존하는 대신 제한을 직접 적용합니다:
XMLReader로 파싱됩니다 — Apache Camel의 XmlConverter.createSAXParserFactory()가 camel-xslt가 자체적으로 SAXSource로 변환하는 본문에 사용하는 것과 동일한 구성입니다. 호출자가 구성한 XMLReader를 가진 SAXSource는 그대로 사용되며, DOMSource와 StAXSource는 이미 파싱되어 있습니다.document() 함수가 변환 시점에 가져오는 리소스는 애플리케이션 자체의 URIResolver가 해석하지 않는 한 거부되며, 이 제한은 변환에 사용할 무언가를 제공하는 모든 진입점에 설치됩니다 — Xalan이 팩토리 리졸버를 복사하지 않는 SAX 푸시 진입점의 변환기도 포함됩니다. 자체 리졸버를 설정하는 애플리케이션 — camel-xslt는 모든 익스체인지에서 그렇게 합니다 — 은 이전과 같이 계속 재정의합니다.main에서 수정됨
9a570b64 및
9dd11779,
3.33.x로 백포트됨
ad9c5236 및
3d886769.
javax.xml.transform.Source를 xslt 엔드포인트에 전달하지 마십시오. 메시지 본문을 String, byte[] 또는 InputStream으로 남겨두어 Apache Camel이 먼저 외부 엔티티가 비활성화된 SAXSource로 변환하도록 하십시오.Source 본문에 대한 convertBodyTo는 우회 방법이 아닙니다: 해당 변환은 동일한 팩토리를 통해 항등 변환을 수행합니다. 재현 코드의 프로브 5가 그 항등 변환이며, 유출됩니다.TransformerFactory.newInstance()에 의존하는 대신 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl을 명시적으로 지정하여 JDK 구현을 요청해야 합니다. 프로브 6이 그 대조군이며, 읽기를 거부합니다.이 저장소는 교육 및 방어 목적으로 게시됩니다: Apache Camel Quarkus 사용자가 취약점을 이해하고, 영향을 받는지 확인하고, 업그레이드가 문제를 해결하는지 확인할 수 있도록 돕기 위함입니다. 소유하거나 운영하지 않는 시스템에 이 자료를 사용하지 마십시오.