Skip to main content
Vulnerability Database/CVE-2025-13473

CVE-2025-13473: Django mod_wsgi Authentication Bypass

CVE-2025-13473 is a timing attack vulnerability in Django mod_wsgi authentication that enables remote attackers to enumerate user accounts. This article covers the technical details, affected versions, security impact, and mitigation.

Updated:

CVE-2025-13473 Overview

CVE-2025-13473 is a timing attack vulnerability in the Django web framework that allows remote attackers to enumerate valid usernames. The flaw affects the django.contrib.auth.handlers.modwsgi.check_password() function used for authentication via mod_wsgi. Attackers measure response time differences to distinguish valid users from invalid ones, enabling targeted credential attacks. The issue is categorized under [CWE-208] Observable Timing Discrepancy. Django maintainers credit Stackered for reporting the vulnerability. Affected branches include Django 6.0 before 6.0.2, 5.2 before 5.2.11, and 4.2 before 4.2.28. Earlier unsupported series such as 5.0.x, 4.1.x, and 3.2.x were not evaluated and may also be impacted.

Critical Impact

Remote attackers can enumerate valid Django user accounts through timing analysis of mod_wsgi authentication responses, enabling targeted credential-stuffing and brute-force campaigns.

Affected Products

  • Django 6.0 before 6.0.2
  • Django 5.2 before 5.2.11
  • Django 4.2 before 4.2.28

Discovery Timeline

  • 2026-02-03 - Django releases security advisory crediting Stackered
  • 2026-02-03 - CVE-2025-13473 published to NVD
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2025-13473

Vulnerability Analysis

The vulnerability resides in django.contrib.auth.handlers.modwsgi.check_password(), a helper that integrates Django's authentication system with Apache's mod_wsgi module. When mod_wsgi validates credentials against Django, the function performs different operations depending on whether the submitted username corresponds to an existing account. Those branching code paths complete in measurably different amounts of time.

An unauthenticated remote attacker can issue repeated authentication requests with varying usernames. By timing the server responses, the attacker distinguishes requests that triggered a password comparison against a stored hash from requests that short-circuited on an unknown user. The outcome is reliable user enumeration without any valid credentials.

The vulnerability does not expose passwords or grant direct access. Its value to an attacker lies in reconnaissance: validated username lists feed credential stuffing, password spraying, and targeted phishing against confirmed accounts.

Root Cause

The root cause is a side-channel introduced by non-constant-time control flow. When the supplied username does not exist, check_password() returns early. When the username exists, Django executes the full password hashing comparison, which is computationally expensive. The time delta between the two paths is large enough to be measured over a network. Secure authentication requires that lookup and comparison operations take the same amount of time regardless of whether the account exists.

Attack Vector

Exploitation requires network access to a Django application configured to use mod_wsgi authentication through AuthType Basic with WSGIAuthUserScript. The attacker submits HTTP Basic authentication attempts and records server response latency. Statistical analysis over multiple samples per username reveals which accounts exist. No authentication, user interaction, or elevated privileges are needed to collect timing samples, though exploitation is specific to the mod_wsgi authentication handler and not Django's standard login views.

Detect Identity Attacks the Moment Authentication Fails

Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.

Stop Identity Attacks

Detection Methods for CVE-2025-13473

Indicators of Compromise

  • High volume of HTTP 401 responses from endpoints protected by mod_wsgi authentication, originating from a single source or small set of IP addresses.
  • Sequential authentication attempts using dictionary-style username lists against the same resource.
  • Request patterns showing uniform password values paired with iterating usernames, consistent with enumeration rather than credential guessing.

Detection Strategies

  • Baseline authentication request rates per source IP and alert on deviations against mod_wsgi-protected paths.
  • Inspect web server access logs for repeated 401 responses with varied Authorization headers from the same client.
  • Correlate response-time variance in authentication endpoints with request volume to identify timing-sample collection behavior.

Monitoring Recommendations

  • Enable verbose logging on Apache mod_wsgi authentication endpoints and forward logs to a centralized analytics platform.
  • Track Django authentication failure metrics and alert when enumeration-style patterns exceed thresholds.
  • Monitor for user-agent strings and request cadences associated with automated scanning tools.

How to Mitigate CVE-2025-13473

Immediate Actions Required

  • Upgrade Django to version 6.0.2, 5.2.11, or 4.2.28 as appropriate for your deployment branch.
  • Inventory applications using django.contrib.auth.handlers.modwsgi to identify exposed authentication endpoints.
  • Apply rate limiting and account lockout policies on mod_wsgi-authenticated routes to constrain enumeration throughput.

Patch Information

The Django project released fixed versions 6.0.2, 5.2.11, and 4.2.28 on 2026-02-03. Refer to the Django Security Release Blog Post and the Django Security Release Notes for upgrade instructions. Users of unsupported branches such as 5.0.x, 4.1.x, and 3.2.x should migrate to a supported release, since those series were not evaluated and may remain vulnerable.

Workarounds

  • Replace mod_wsgi authentication with Django's standard login views, which are not affected by this specific function.
  • Place authentication endpoints behind a reverse proxy or Web Application Firewall that enforces per-source request throttling.
  • Introduce artificial response-time jitter at the proxy layer to blur timing differences until patching is complete.
bash
# Configuration example
pip install --upgrade "Django>=4.2.28,<4.3"
# or
pip install --upgrade "Django>=5.2.11,<5.3"
# or
pip install --upgrade "Django>=6.0.2,<6.1"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.