Skip to content

Add Apache NiFi ExecuteGraphQuery Tinkerpop Groovy RCE module (CVE-2026-39816) - #21852

Open
M4xSec wants to merge 2 commits into
rapid7:masterfrom
M4xSec:apache-nifi-tinkerpop-groovy-rce
Open

Add Apache NiFi ExecuteGraphQuery Tinkerpop Groovy RCE module (CVE-2026-39816)#21852
M4xSec wants to merge 2 commits into
rapid7:masterfrom
M4xSec:apache-nifi-tinkerpop-groovy-rce

Conversation

@M4xSec

@M4xSec M4xSec commented Aug 31, 2026

Copy link
Copy Markdown

Summary

Exploit module for CVE-2026-39816. The TinkerpopClientService in Apache NiFi
2.0.0-M1 through 2.8.0 is missing the @Restricted annotation that carries the
Execute Code required permission, and the ExecuteGraphQuery /
ExecuteGraphQueryRecord processors that use it are not gated by Execute Code
either. The processor compiles and evaluates its "Graph Query" with a local
GremlinGroovyScriptEngine before it ever connects to a graph database, so a
flow author who has been explicitly denied Execute Code (the policy that guards
ExecuteScript and ExecuteProcess), but who still has read/write on a process
group and the controller, can create the service in bytecode-submission mode
plus an ExecuteGraphQuery whose query is Groovy, and run code as the NiFi
service account. This bypasses the restriction that NiFi's Restricted machinery
is meant to enforce.

Exploitation needs the optional graph bundle (nifi-other-graph-services-nar,
which ships TinkerpopClientService) installed; servers without it are not
affected. Fixed in NiFi 2.9.0.

NiFi 2.x secured installations have no local login, so the module drives the
Spring Security OIDC login (authorize redirect, credential POST, callback) to
obtain the NiFi JWT from USERNAME/PASSWORD, or accepts an existing
BEARER-TOKEN. It creates the controller service and processor, runs a command
payload, and removes both components on cleanup. NiFi does not disclose its
version on the unauthenticated API, so check confirms the API is reachable and
reports Detected when the build is not disclosed.

Verification

  • Install Apache NiFi 2.0.0-M1 - 2.8.0 with the nifi-other-graph-services-nar bundle and OIDC configured
  • Create a flow author account (read/write on the root process group and controller; Execute Code may be denied)
  • use exploit/linux/http/apache_nifi_tinkerpop_groovy_rce
  • set RHOSTS, VHOST, USERNAME, PASSWORD (or BEARER-TOKEN), LHOST, PAYLOAD
  • check reports the NiFi API is reachable
  • run
  • A session opens as the NiFi service account, and the created service and processor are removed on cleanup

Tested against Apache NiFi 2.8.0 fronted by Keycloak OIDC.

Adds an exploit module for CVE-2026-39816. The TinkerpopClientService in
Apache NiFi 2.0.0-M1 through 2.8.0 is missing the Restricted annotation that
carries the Execute Code required permission, and the ExecuteGraphQuery /
ExecuteGraphQueryRecord processors that drive it are not gated by Execute Code
either. A flow author who has been explicitly denied Execute Code, but still
has read/write on a process group and the controller, can create the service
in bytecode-submission mode and an ExecuteGraphQuery whose Graph Query is
Groovy. The processor compiles and evaluates the Groovy with a local
GremlinGroovyScriptEngine before any graph traversal, so it runs as the NiFi
service account and bypasses the restriction. Fixed in 2.9.0.

The module logs in through the configured OpenID Connect provider (NiFi 2.x
secured mode has no local login), or takes an existing bearer token, creates
the controller service and processor, runs a command payload, and removes both
components on cleanup.

Tested against Apache NiFi 2.8.0 fronted by Keycloak OIDC.

Signed-off-by: venexy <predator0x300@gmail.com>
@h00die

h00die commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

nifi is available on docker. can you create a dockerfile or comparable (docker compose) that setups up the environment in a way that can be exploited?

The module only authenticated through the external OIDC flow, so it could
not log in to a stock single-user or LDAP-backed NiFi, which are the common
lab and on-prem setups. Read authentication/configuration and, when
externalLoginRequired is false, post the credentials to /access/token for the
bearer token; keep the OIDC dance for federated installs. USERNAME and
PASSWORD now work against either, and BEARER-TOKEN still short-circuits both.

Verified end to end against a single-user 2.8.0 lab with the graph bundle: a
flow author denied Execute Code gets 403 on ExecuteScript while
ExecuteGraphQuery runs Groovy as the nifi user.

Signed-off-by: venexy <predator0x300@gmail.com>
@M4xSec

M4xSec commented Aug 31, 2026

Copy link
Copy Markdown
Author

Hi @h00die

Added a docker-compose lab for it:
https://github.com/M4xSec/My-Exploits/tree/main/docker-lab/nifi-cve-2026-39816

README has the run steps and the module invocation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants