ZeroPathAI/nifi-CVE-2026-39816-poc
GitHub: ZeroPathAI/nifi-CVE-2026-39816-poc
针对 Apache NiFi 2.8.0 中 TinkerpopClientService 缺少权限注解导致的 EXECUTE_CODE 绕过漏洞的完整 PoC,含自动环境搭建和交互式反向 Shell 利用脚本。
Stars: 0 | Forks: 0
# Apache NiFi CVE-2026-39816 POC
CVE-2026-39816 的概念验证演示,这是 Apache NiFi 2.8.0 中的一个 `EXECUTE_CODE` 权限绕过漏洞,允许被故意拒绝代码执行权限的 flow 设计者通过 graph bundle 的 `ExecuteGraphQuery` 处理器在 NiFi JVM 中运行任意 Groovy 代码。
- 在 NiFi 2.9.0 中已修复
- 由 ZeroPath 发现 -- 完整的技术分析可在 ZeroPath 网站上查看。
## 漏洞详情
### TinkerpopClientService 缺少 `@Restricted` 注解 (CVE-2026-39816, CWE-95)
NiFi 通过 `@Restricted(requiredPermission = RequiredPermission.EXECUTE_CODE)` 注解,将执行代码的处理器限制在 `EXECUTE_CODE` 权限之后。NiFi 中所有 16 个专用脚本组件 —— `ExecuteScript`、`InvokeScriptedProcessor`、`ExecuteGroovyScript`、`ScriptedTransformRecord` 等 —— 都带有此注解,因此 flow 设计者必须获得明确的 `EXECUTE_CODE` 权限,授权层才会允许他们创建或配置这些处理器。
graph bundle (`nifi-graph-nar` + `nifi-other-graph-services-nar`) 提供了第三个缺少此注解的代码执行路径:
```
// nifi-extension-bundles/nifi-graph-bundle/nifi-other-graph-services/
// src/main/java/org/apache/nifi/graph/TinkerpopClientService.java:451
protected Map bytecodeSubmission(
String s, Map map, GraphQueryResultCallback cb) {
...
compiled = groovyShell.parse(s); // line 463 — compile attacker string
compiledCode.put(s, compiled);
...
compiled.setBinding(bindings);
Object result = compiled.run(); // line 477 — execute in NiFi JVM
```
`s` 参数是来自 `ExecuteGraphQuery` 处理器“Graph Query”属性的查询字符串,原封不动地传递过来。这里没有任何过滤、没有允许列表,也没有沙箱 —— 任何有效的 Groovy 代码都会被编译并以 NiFi 进程的完整权限执行。
无论是 `TinkerpopClientService`,还是驱动它的 `ExecuteGraphQuery` / `ExecuteGraphQueryRecord` 处理器,都没有带有 `@Restricted` 注解。因此,NiFi 的授权层将它们视为普通组件,被明确拒绝 `EXECUTE_CODE` 权限的 flow 设计者仍然可以创建它们。
### 服务器何时可被利用?
当以下**两个**条件同时满足时,NiFi 2.8.0 服务器可被利用:
1. **安装了可选的 graph bundle。** 具体来说是 `nifi-other-graph-services-nar` NAR —— 这是包含 `TinkerpopClientService` 的 bundle。没有此 NAR 的服务器不受影响。
2. **至少有一个用户拥有 flow 设计者风格的权限(对某个 process group 和 `/controller` 具有 `read`/`write` 权限),但没有 `EXECUTE_CODE` 权限。** 这是一种常见的策略形态:组织希望用户能够构建和修改管道,但不能运行任意代码。`EXECUTE_CODE` 权限正是该策略旨在执行的安全边界。
如果这两个条件都成立,用户可以在“ByteCode Submission”模式下配置 `TinkerpopClientService`,将其指向任何可达的 Gremlin 服务器(Gremlin 服务器仅用于服务初始化 —— 执行发生在本地),并创建一个在“Graph Query”属性中包含 Groovy 代码的 `ExecuteGraphQuery` 处理器。启动该处理器会在 NiFi JVM 中编译并运行 Groovy 代码。
### 攻击者能做什么?
以 NiFi 服务账户身份执行任意代码。在此基础上:
- 读取和修改 NiFi 主机文件系统上的所有内容,包括 keystore、敏感属性密钥以及任何由 flow 加密的密钥。
- 访问 NiFi 能触及的所有内部系统。NiFi 通常在其 Parameter Contexts 和 Controller Services 中拥有数据仓库、消息总线、对象存储和数据库的凭据 —— Groovy payload 可以读取所有这些凭据并进行内网渗透。
- 通过写入 `flow.json.gz`、将 NAR 投放到自动加载目录或修改 controller 服务来建立持久化。
该漏洞利用绕过了 `EXECUTE_CODE` 权限,因此即使操作员明确撤销了用户的代码执行权限,此攻击依然有效 —— 而这正是该权限存在的意义所在。
### POC 范围
本仓库提供了**一个** POC,涵盖了最直接的触发方式:攻击者控制的 Groovy 代码被直接放置在 `Graph Query` 处理器属性中。不需要上游连接、不需要 Expression Language、不需要 FlowFile 内容 —— 只需要自行在计时器上运行的处理器。
还存在另外两个代码路径(当 `Graph Query` 为空时,使用 FlowFile 正文内容作为查询;以及将受攻击者影响的 FlowFile 属性通过 Expression Language 插值到查询模板中)。这里没有演示它们,因为它们在满足额外前置条件后才能到达同一个漏洞利用点;直接路径已经足以证明 `EXECUTE_CODE` 绕过。
## 仓库内容
- **`setup/`** — Docker Compose 环境。启动一个 NiFi 2.8.0 实例(官方 `apache/nifi:2.8.0` 镜像),并自动加载 graph bundle NARs、一个提供两个测试用户(`admin` 和 `flow_designer`)的 LDAP 服务器,以及一个供 `TinkerpopClientService` 指向的 Gremlin 服务器。`setup.sh` 会引导配置策略,使得 `flow_designer` 拥有 flow 编辑权限,但**没有** `EXECUTE_CODE` 权限,然后验证配置。
- **`pocs/flow_designer_groovy_rce.py`** — 独立漏洞利用脚本。以 `flow_designer` 身份进行身份验证,演示 `ExecuteScript` 被拒绝(证明 `EXECUTE_CODE` 限制正在生效),然后创建一个 `TinkerpopClientService` + `ExecuteGraphQuery`,其包含的 Groovy payload 会生成一个 bash 反向 shell 连接到 POC 在本地启动的监听器。连接建立后,POC 通过 util-linux 的 `script` 将 shell 升级为完全交互式 PTY 支持的 bash,并带有原始模式 stdio 桥接和实时窗口大小调整功能 —— 操作员可以获得一个位于 NiFi 容器内的真实终端。
## 使用说明
前置条件:Docker、Python 3.10+ 以及 [uv](https://docs.astral.sh/uv/getting-started/installation/)。
```
cd setup
./setup.sh
```
首次运行会从 Maven Central 下载 graph-bundle NARs 并拉取 Docker 镜像(约 2-3 分钟)。设置完成后,它会打印出可直接粘贴运行的 POC 调用命令。
运行 POC:
```
uv run --no-project --with requests \
pocs/flow_designer_groovy_rce.py \
--base-url https://localhost:8443 \
--username flow_designer \
--password 'flowDesigner123!' \
--gremlin-host gremlin-server
```
POC 会让操作员进入 NiFi 容器内的交互式 bash 会话,以 `nifi` 服务账户身份运行。输入 `exit` 或按 `Ctrl-D` 断开连接 —— 之后 POC 将清理其创建的处理器和 controller 服务。
在 Linux Docker 上(默认情况下无法解析 `host.docker.internal`),请传递 `--shell-host ` 或在 `setup/docker-compose.yml` 的 `nifi` 服务中添加 `extra_hosts: ["host.docker.internal:host-gateway"]`。
清理拆除:
```
cd setup
./teardown.sh
```
标签:Apache NiFi, Checkov, CISA项目, CVE-2026-39816, CWE-95, Groovy脚本, POC, RCE漏洞, Tinkerpop, Web报告查看器, 任意代码执行, 权限绕过, 版权保护, 网络安全, 请求拦截, 逆向工具, 隐私保护, 零日漏洞