
Apache Camelの脆弱性を再現する実行可能なPoCです。この脆弱性では、jgroupsコンシューマがフィルタなしでクラスタメッセージをJavaデシリアライズしていました。JGroupsEndpoint.createExchange(Message) は、コンシューマが受信するすべてのメッセージに対して呼び出され、org.jgroups.Message.getObject() からexchangeのボディを設定していました。ObjectMessage(Camelのjgroupsプロデューサが送信する型)の場合、JGroupsはメッセージの到着時に ObjectInputStream を介してペイロードをJavaデシリアライズし、getObject() がその結果を返します。java.io.ObjectInputFilter は適用されていなかったため、クラスタから受信したアプリケーションのクラスパス上の任意のシリアライズ可能クラスがインスタンス化され、そのデシリアライズコールバックが実行されました。利用可能なガジェットチェーンが存在する場合、リモートコード実行につながります。標準の new JChannel() スタック(UDPマルチキャスト、AUTH なし、暗号化なし)では、クラスタに到達できる任意のホストが認証情報なしでそのようなメッセージを送信できます(CWE-502)。
Spring Bootのみ。 この再現環境にはCamel Spring Bootモジュールが1つだけ含まれています。
camel-jgroupsにはcamel-quarkus-jgroups拡張機能が存在しないため、再現するQuarkus版の対応物はありません。Spring Bootモジュールは、影響を受ける動作および修正後の動作を示します。
| ランタイム | ディレクトリ | スタック |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-jgroups 4.22.0(影響あり、修正版 4.22.1) |
無害な攻撃者オブジェクト — com.example.Marker は、修正版のデフォルト許可リスト(java.**、javax.**、org.apache.camel.**)に含まれない通常のアプリケーションクラスです — をJGroupsのワイヤ形式にシリアライズし、実際の JGroupsEndpoint.createExchange(...) に渡します。このメソッドは Message.getObject() でそれを読み取ります(コンシューマが受信メッセージごとに行うのと同じ呼び出しです)。チャネルやマルチキャストは不要なため、チェックは決定的です。Marker.readObject はフラグを反転させてデシリアライズコールバックが実行されたことを示します — 実際のガジェットチェーンはまさにその時点で有害なコードを実行しますが、この再現環境にはガジェットは含まれていません。
com.example.Marker を拒否し、createExchange が JGroupsException をスローします。オブジェクトはルートに到達しません。正直な注意点(アドバイザリが述べているとおり): 4.22.1 / 4.18.5 のクラスチェックは、JGroupsがペイロードをデシリアライズした後に実行されるため、修正版ビルドでも
readObjectコールバックは依然として実行されます — これは多層防御です。デシリアライズ中に実行されるコードを阻止するには、JVM全体の-Djdk.serialFilterを設定し、チャネルをAUTH+ 暗号化で保護する必要もあります。さらに 4.23.0 では、これらの制御のいずれかが設定されていない限りコンシューマの起動を拒否します。この再現環境はクラスチェックの差分を示しており、コールバック実行フラグによってこの注意点が可視化されます。
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: Marker deserialized + routed; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -jar target/cve-2026-88900-jgroups-deserialization-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: JGroupsException rejects com.example.Marker; >>> Not exploited
| 項目 | 値 |
|---|---|
| コンポーネント | camel-jgroups (JGroupsEndpoint.createExchange) |
| CWE | CWE-502 (信頼できないデータのデシリアライズ) |
| 深刻度 | HIGH |
| 攻撃ベクトル | クラスタのマルチキャストグループ / バインドポートに到達できるホストが、細工された ObjectMessage を送信する。コンシューマーはフィルタなしでこれをデシリアライズする |
| 影響 | ガジェットチェーンがクラスパス上にある場合、Camel プロセス内でリモートコード実行が可能。それ以外の場合でも任意のクラスのインスタンス化が可能 |
| 影響を受けるバージョン | 4.0.0 から 4.18.5 未満、4.19.0 から 4.22.1 未満 |
| 修正済みバージョン | 4.18.5、4.22.1、4.23.0 |
| JIRA | CAMEL-24676、CAMEL-25223 |
| 報告者 | h1ei1 |
アドバイザリ: https://camel.apache.org/security/CVE-2026-88900.html
JGroupsEndpoint は、エクスチェンジがルーティングされる前に、Message.getObject() が返すボディのクラスを新しい deserializationFilter オプション (jdk.serialFilter 構文) を通じてチェックするようになりました。このオプションが設定されていない場合は、JVM 全体の jdk.serialFilter が存在すればそれが尊重され、そうでなければ保守的なデフォルトの許可リストが java.**/javax.**/org.apache.camel.** を許可し、java.net.** を拒否し、それ以外はすべて拒否します。拒否されたメッセージはコンシューマーの ExceptionHandler に報告され、ルーティングされません。4.23.0 (CAMEL-25223) では、デシリアライズより前に作用する制御 (JVM 全体のフィルタ、jgroups.deserialization.filter システムプロパティ、または AUTH+暗号化チャネル) が設定されていない限り、コンシューマーは起動を拒否するようになりました。acceptAllObjects=true は以前の動作を復元しますが、安全でない設定としてフラグが立てられます。
コンシューマーを実行する JVM に -Djdk.serialFilter を設定し (ルートがクラスタ上でやり取りするクラスのみを許可する)、channelProperties オプションを介して AUTH と SYM_ENCRYPT/ASYM_ENCRYPT でチャネルを保護し、クラスタのマルチキャストグループやバインドポートを信頼できないネットワークに公開しないでください。
このリポジトリは教育および防御目的で公開されています。Apache Camel ユーザーが脆弱性を理解し、影響を受けているかどうかを確認し、アップグレードによって解決されることを検証できるようにするためです。デシリアライズされるオブジェクトはこのリポジトリで定義された無害なマーカークラスであり、ガジェットチェーンを含まず、有害な動作も行いません。所有または運用していないシステムに対してこの資料を使用しないでください。