TransformerFactory が JAXP の外部アクセス制限を無効化するApache Camel Quarkus の脆弱性に対する実行可能な概念実証(PoC)再現コードです。この脆弱性では、XSLT サポート拡張(camel-quarkus-support-xalan)が独自の Xalan ベースの TransformerFactory を xslt コンポーネントに提供し、それを JAXP のデフォルトとして登録します。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 Quarkus 拡張機能であり、Camel コンポーネントではありません。通常の 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
影響を受けるビルドでの期待される出力(抜粋 — ドライバーは 6 つのプローブを実行します。詳細は
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 issue | 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 はすべての exchange でそうしています — は、
従来どおりそれを上書きし続けます。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 ユーザーが脆弱性を理解し、 影響を受けているかどうかを確認し、アップグレードによって解決されることを確認できるようにするためです。 所有または運用していないシステムに対してこの資料を使用しないでください。