CVE-2015-0219
NoneCVSS
—
EPSS
7.0%
Published
Jan 16, 2015
CISA due date
—
Cloudanix analysis
Some older Django websites can be tricked into accepting a fake user identity sent in a specially named request header.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Low
- Impact
- Privilege Gain
- Component
- Web Framework
- Class
- Authentication Bypass
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Django versions before 1.4.18, 1.6.10, and 1.7.3 can incorrectly treat HTTP headers containing underscores as equivalent to headers containing dashes after WSGI/CGI normalization. Because many authentication and authorization integrations trust reverse-proxy-supplied headers such as user identity or role headers, a remote unauthenticated attacker may be able to inject a spoofed header like X-Auth_User that is normalized into the same application variable as X-Auth-User. The direct impact is integrity compromise of request metadata, which can lead to authentication bypass or privilege confusion in applications that rely on trusted inbound headers.
Why it matters to the business
Applications using affected Django versions may allow users to impersonate other users or gain access intended only for authenticated users if the application trusts identity headers from a proxy or single sign-on layer. The risk is highest for internet-facing Django deployments behind reverse proxies, SSO gateways, or middleware that pass user identity through HTTP headers. Although this issue is old and not in the CISA KEV catalog, public exploit knowledge exists and legacy Django deployments remain exposed if they were never upgraded.
How an attack unfolds
An attacker sends a crafted HTTP request directly to a vulnerable Django application or through an intermediary that does not block underscore-containing headers. Instead of sending the legitimate trusted header name with a dash, the attacker sends a visually similar header using an underscore, such as X-Auth_User. During WSGI normalization, both the dashed and underscored forms can map to the same request metadata key, such as HTTP_X_AUTH_USER. If the application, middleware, or authentication integration uses that metadata key as proof of identity, the attacker-controlled value may be accepted as if it came from a trusted proxy or authentication gateway. The attacker can then access protected functionality as another user or with elevated application privileges, depending on how the trusted header is used.
How to fix it
Upgrade Django to a fixed release: 1.4.18 or later for the 1.4 branch, 1.6.10 or later for the 1.6 branch, or 1.7.3 or later for the 1.7 branch. Prefer upgrading to a currently supported Django release because all affected branches are long end-of-life. As defense in depth, configure front-end proxies and web servers to reject or drop request headers containing underscores, and ensure the application is not reachable directly except through the trusted proxy path. Review authentication middleware and application code for any use of request.META, HTTP_* variables, REMOTE_USER-style headers, X-Auth-User, X-Forwarded-User, or other identity-bearing headers, and only trust those values when they are set by a controlled upstream component after untrusted client-supplied versions have been stripped.
How to confirm the fix worked
Confirm the deployed Django version is 1.4.18, 1.6.10, 1.7.3, or newer, and ideally a currently supported release. Verify package inventories, lockfiles, virtual environments, and running application images rather than relying only on source repositories. Test the running service by sending a request with an underscore-containing identity header, such as X-Auth_User, and confirm it is rejected, removed by the proxy, or ignored by application authentication logic. Confirm reverse proxies and web servers are configured to drop headers with underscores and that direct network access to the Django application server is blocked from untrusted networks. Regression-test any header-based SSO or proxy-authentication flows after patching to ensure legitimate trusted headers still work only through the intended proxy path.
Typical attack path
- Identify a Django application using an affected version prior to 1.4.18, 1.6.10, or 1.7.3.
- Determine whether the application trusts HTTP headers for authentication, user identity, roles, tenant selection, or authorization decisions.
- Send requests containing underscore-based variants of trusted headers, such as X-Auth_User instead of X-Auth-User.
- Observe whether the application treats the spoofed header value as authenticated or privileged request metadata.
- Use the accepted spoofed identity or authorization context to access protected pages, APIs, or administrative functions.
How to detect it
To determine whether exploitation already occurred, review web server, reverse proxy, WAF, load balancer, and application access logs for HTTP request headers containing underscores, especially identity-related headers. Focus on requests to login-protected APIs, administrative pages, account management paths, or actions that changed data. Look for unusual combinations where a request lacks a normal authenticated session but includes headers such as X-Auth_User, X-Forwarded_User, X-Remote_User, Remote_User, or other organization-specific identity headers with underscores. In application logs, correlate suspicious requests with unexpected authenticated usernames, sudden privilege changes, anomalous user switching from the same source IP, or protected endpoint access without the expected SSO/session artifacts. If packet captures, WAF event bodies, or full-fidelity HTTP telemetry are available, search raw headers because many access log formats do not record request headers by default. Also review proxy configuration and logs for evidence that the backend was reachable directly, since direct-to-backend access materially increases exploitation likelihood.
- X-Auth_User:
- X-Forwarded_User:
- X-Remote_User:
- X-User_Name:
- X-Authenticated_User:
- Remote_User:
- HTTP_X_AUTH_USER
- HTTP_X_FORWARDED_USER
- HTTP_X_REMOTE_USER
- HTTP_REMOTE_USER
- _User:
- _USER
What your security team should do
- Prioritize remediation for any internet-facing or externally reachable Django application that uses proxy-based, SSO-based, or header-based authentication.
- Upgrade affected Django installations to fixed or supported versions; treat legacy 1.4, 1.6, and 1.7 branches as unsupported technical debt requiring migration.
- Configure reverse proxies, load balancers, and web servers to reject or strip HTTP request headers containing underscores before traffic reaches Django.
- Review application and middleware code for trust in HTTP_* request metadata and remove reliance on client-controllable headers for authentication or authorization.
- Block direct access to application backends so requests must pass through the hardened proxy or authentication gateway.
- Search historical access logs for underscore-containing identity or authorization headers and investigate any successful requests to protected endpoints using those headers.
- Add automated tests and WAF/SIEM detections for suspicious headers such as X-Auth_User, X-Forwarded_User, X-Remote_User, and similar underscore variants.
The record
Django before 1.4.18, 1.6.x before 1.6.10, and 1.7.x before 1.7.3 allows remote attackers to spoof WSGI headers by using an _ (underscore) character instead of a - (dash) character in an HTTP header, as demonstrated by an X-Auth_User header.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| PyPI | django | 0 | 1.4.18 |
| PyPI | django | 1.6 | 1.6.10 |
| PyPI | django | 1.6.0 | 1.6.10 |
| PyPI | django | 1.7 | 1.7.3 |
| PyPI | django | 1.7.0 | 1.7.3 |
| Debian:11 | python-django | 0 | 1.7.1-1.1 |
| Debian:12 | python-django | 0 | 1.7.1-1.1 |
| Debian:13 | python-django | 0 | 1.7.1-1.1 |
| Debian:6.0 | python-django | 0 | 1.2.3-3+squeeze12 |
| Debian:7 | python-django | 0 | 1.4.5-1+deb7u9 |
| Mageia:4 | python-django | 0 | 1.5.9-1.1.mga4 |
| Mageia:4 | python-django14 | 0 | 1.4.18-1.1.mga4 |
| SUSE:Enterprise Storage 1.0 | python-Django | 0 | 1.6.11-4.1 |
| Ubuntu:14.04:LTS | python-django | 0 | 1.6.1-2ubuntu0.6 |
| openSUSE:Tumbleweed | python-bjoern | 0 | 1.4.2-1.23 |
| openSUSE:Tumbleweed | python-bjoern | 0 | 3.2.2-1.10 |
| pypi | Django | 1.6 | No fix |
| pypi | Django | 1.7 | No fix |
Related vulnerabilities
- GHSA-8p8v-wh79-9r56 Django vulnerable to Uncontrolled Resource Consumption Also affects django
- GHSA-mjgh-79qc-68w3 Django has a Race Condition vulnerability Also affects django
- CVE-2026-25673 An issue was discovered in 6.0 before 6.0.3, 5.2 before 5.2.12, and 4.2 before 4.2.29. Also affects django
- CVE-2026-25674 An issue was discovered in 6.0 before 6.0.3, 5.2 before 5.2.12, and 4.2 before 4.2.29. Also affects django
- GHSA-6426-9fv3-65x8 Django has an SQL Injection issue Also affects django
- GHSA-gvg8-93h5-g6qq Django has an SQL Injection issue Also affects django
- GHSA-2mcm-79hx-8fxw Django has Observable Timing Discrepancy Also affects django
- GHSA-33mw-q7rj-mjwj Django has Inefficient Algorithmic Complexity Also affects django