Many modern web applications rely on a flawed assumption: backends can blindly trust security-critical headers from upstream reverse proxies. This assumption breaks down because HTTP RFC flexibility allows different servers to interpret the same header field in fundamentally different ways, creating exploitable gaps that attackers are increasingly targeting.
Two recent CVEs I discovered expose this systemic problem and demonstrate why these are not isolated bugs, but symptoms of a much broader architectural flaw. When CVE-2025-48865 in Fabio and CVE-2025-64484 in OAuth2-proxy both enable identical attack patterns across completely different technologies, it reveals that our industry has fundamentally misunderstood where the real security boundaries lie.
TL;DR: Two newly discovered CVEs (CVE-2025-48865 in Fabio, CVE-2025-64484 in OAuth2-proxy) expose a systemic vulnerability in how reverse proxies handle header processing. By exploiting hop-by-hop header stripping and underscore-hyphen normalization differences, attackers can bypass proxy security controls to achieve authentication bypass and privilege escalation. These are not isolated bugs. They are symptoms of a fundamental trust boundary problem in modern proxy-backend architectures.
Hop-by-Hop Header Abuse in Fabio (CVE-2025-48865)
In a typical setup, reverse proxies strip untrusted client headers and inject their own security-critical values (such as X-Forwarded-For and X-Real-IP), which backends then use for authentication and access control decisions.
However, HTTP's Connection header allows clients to designate certain headers as "hop-by-hop," meaning they should be processed only by the immediate recipient and stripped before forwarding. By setting something like:
Connection: close, X-Forwarded-Host
an attacker can trick the proxy into removing security headers it would normally preserve and trust.
This attack method has surfaced across multiple reverse proxy implementations, including Apache HTTP Server (CVE-2022-31813) and Traefik (CVE-2024-45410). I discovered that Fabio was susceptible to the same abuse by including security-critical headers like Forwarded in the Connection header, causing Fabio to strip them before forwarding the request to the backend.
What is a hop-by-hop header attack?
HTTP's Connection header was designed to let clients specify which headers are "hop-by-hop": they should only be processed by the immediate recipient (the proxy) and removed before forwarding to the next server.
Attackers abuse this by listing security-critical headers like X-Forwarded-For or X-Real-IP in the Connection header, tricking the proxy into stripping headers that the backend relies on for authentication and access control.
Normal flow:
Client --> Proxy (preserves X-Forwarded-For) --> Backend (uses it for auth)
Attack flow:
Client sends: Connection: close, X-Forwarded-For
Client --> Proxy (strips X-Forwarded-For!) --> Backend (auth logic never triggers)
Why stripping these headers is dangerous
Headers like X-Real-IP and X-Forwarded-For often drive access control decisions, determining whether a request is internal or external, or whether a sensitive endpoint should be accessible.
For example, ProjectDiscovery's research into Versa Concerto found that the application relied on X-Real-IP to restrict access to Spring Boot Actuator endpoints. If that header gets stripped, the security logic simply never triggers.
The Underscore-Hyphen Normalization Problem
Header normalization creates yet another attack vector that exploits the same fundamental trust boundary weakness. Many web application frameworks automatically normalize header names during processing:
| Framework Behavior | Example |
|---|---|
| Capitalize + standardize separators |
client-verified becomes Client-Verified
|
| Case normalization |
x-real-ip treated same as X-Real-IP
|
| Underscore-to-hyphen conversion |
x_forwarded_email becomes X-Forwarded-Email
|
These normalization differences create systematic opportunities for attackers to smuggle headers using variations that proxy servers don't recognize, but backends will normalize and process as trusted security headers.
Deutsche Telekom Security's research specifically highlighted this underscore-hyphen normalization problem. Different frameworks handle it inconsistently: some convert hyphens to underscores, while others make headers accessible regardless of the original separator format.
OAuth2-Proxy Authentication Bypass via Underscore Smuggling (CVE-2025-64484)
OAuth2-proxy is an authentication proxy that sits between users and backend applications, handling OAuth2/OIDC authentication flows for applications that don't natively support them. When a user authenticates, OAuth2-proxy forwards the request to the backend along with user information in headers like X-Forwarded-User and X-Forwarded-Email.
Here's the problem: OAuth2-proxy correctly strips X-Forwarded-Email from incoming client requests, but it only filters the standard hyphenated version. Underscore variants like X_Forwarded_Email pass through unfiltered.
When these underscore-based headers reach backend applications that normalize header names (converting them back to the hyphenated form), the backend treats them as trusted authentication headers.
The attack in practice:
# Attacker sends:
GET /admin HTTP/1.1
Host: target.com
X_Forwarded_Email: admin@target.com
# OAuth2-proxy sees X_Forwarded_Email (underscores)
# --> not in its filter list, passes through
# Backend framework normalizes X_Forwarded_Email to X-Forwarded-Email
# --> treats it as trusted auth header
# --> attacker is now authenticated as admin@target.com
The result: an attacker can impersonate any user, including administrators, leading to privilege escalation or full account takeover.
MITRE ATT&CK TTP Mapping
These header injection techniques map to several MITRE ATT&CK tactics:
| Tactic | Technique | How It Applies |
|---|---|---|
| Initial Access | T1190 - Exploit Public-Facing Application | Targeting proxy configurations to bypass auth |
| Defense Evasion | T1562 - Impair Defenses | Circumventing proxy security filters via normalization abuse |
| Privilege Escalation | T1068 | Injecting auth headers to impersonate legitimate users |
| Lateral Movement | -- | Compromised auth may grant access to additional internal systems |
Defending Against Proxy Trust Boundary Attacks
Defending against these vulnerabilities requires precise adherence to the HTTP RFC and careful handling of ambiguous behaviors like header normalization and case sensitivity. Organizations must evaluate how different HTTP servers and frameworks interact before deployment, as these implementation differences create the attack surface.
Key defensive measures:
Sanitize all header variants at the proxy layer. Block underscore variants, case variations, and any other formats that could be normalized by backend frameworks.
Allowlist legitimate hop-by-hop headers. Do not let arbitrary headers be designated as hop-by-hop through the
Connectionheader.Implement backend-side verification. Consider cryptographic signing of authentication headers so backends can validate their authenticity regardless of proxy behavior. (Rarely implemented in practice, but the strongest mitigation.)
Audit your specific proxy-backend combination. The attack depends on parsing mismatches between your proxy and backend framework. Test your actual stack for these gaps.
Keep proxy software patched. Both CVEs discussed here have patches available.
Most importantly, backends should validate rather than blindly trust security-critical headers from proxies. The fundamental lesson from both of these CVEs is the same: when the trust boundary between your proxy and backend is implicit rather than cryptographically enforced, every normalization difference and every protocol ambiguity becomes an attack surface.
Top comments (0)