Cloudanix VulnDB

CVE-2025-13473

Medium · 5.3

CVSS

5.3

EPSS

0.8%

Published

Feb 3, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in some Django-based login checks can let attackers figure out which user accounts exist, making later account attacks easier.

Chainable
Exploitation
Remote Authenticated
Attacker needs
Low Privilege
Complexity
High
Impact
Data Exposure
Component
Web Framework
Class
Information Disclosure
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

The flaw is a timing side channel in Django's `django.contrib.auth.handlers.modwsgi.check_password()` path used for authentication through Apache `mod_wsgi`. When a username is checked, the amount of work performed can differ between existing and non-existing accounts, allowing a remote attacker to infer whether a supplied username is valid by repeatedly measuring authentication response times. The issue affects Django 6.0 before 6.0.2, 5.2 before 5.2.11, and 4.2 before 4.2.28; unsupported series such as 5.0.x, 4.1.x, and 3.2.x may also be affected but were not evaluated. Impact is limited to confidentiality: it does not directly allow code execution, privilege escalation, data modification, or denial of service, but it can disclose valid account identifiers.

Why it matters to the business

Organizations using Django applications with Apache `mod_wsgi` authentication may unintentionally expose which usernames exist. That information can improve the success rate of password spraying, credential stuffing, phishing, help-desk impersonation, and targeted account takeover attempts. The current public exploit maturity is listed as none, EPSS is low at 0.00713, and it is not in CISA KEV or known ransomware use, so this is generally a planned but important remediation rather than an emergency unless the affected authentication surface is internet-facing or protects sensitive business systems.

How an attack unfolds

An attacker first identifies an application using Django's `mod_wsgi` authentication handler, typically by finding a resource protected by Apache/WSGI authentication. The attacker then prepares a list of candidate usernames and sends repeated authentication attempts using each candidate with an intentionally invalid password. By collecting many timing samples per username and comparing response-time distributions, the attacker can distinguish candidates that trigger the real password-verification path from candidates that do not. Network noise makes the attack higher effort and usually requires statistical analysis, but over enough requests the attacker can build a list of valid usernames. The attacker can then use that list for follow-on attacks such as password spraying, credential stuffing, phishing, or targeted social engineering.

How to fix it

Upgrade affected Django deployments to a fixed release: Django 6.0.2 or later, Django 5.2.11 or later, or Django 4.2.28 or later. For source-based consumers, ensure the Django fix corresponding to commit `ba00558ddac694d92b05d12ecd2a5b7fcc1de025` is present; for GitLab source consumers, ensure the relevant dependency update corresponding to commit `064b7e40da0b30ea250d4486cc3f08c5328a4165` is applied. Unsupported Django branches should be upgraded to a supported fixed branch rather than relying on an unvalidated backport. If immediate upgrade is not possible, reduce exposure by limiting access to `mod_wsgi`-authenticated resources, placing them behind VPN or trusted network controls, adding rate limits and lockout protections for repeated authentication failures, and monitoring for username-enumeration patterns. These mitigations reduce exploitability but do not fully remove the timing side channel.

How to confirm the fix worked

Confirm the running Django version is 6.0.2 or later, 5.2.11 or later, or 4.2.28 or later, and verify deployed artifacts are not using an older vendored copy of Django. Review dependency lockfiles, container images, virtual environments, and application package metadata to ensure the fixed version is actually deployed, not merely declared. Check Apache and WSGI configuration for use of Django's `django.contrib.auth.handlers.modwsgi` authentication handler; systems not using this authentication path are not exposed to this specific issue. For source builds, verify the patch containing `ba00558ddac694d92b05d12ecd2a5b7fcc1de025` is present. After patching, perform a controlled timing test with known valid and invalid usernames and confirm there is no statistically meaningful response-time difference attributable to user existence.

Typical attack path

  1. Find an externally reachable Django application that uses Apache `mod_wsgi` authentication.
  2. Access a protected resource that invokes `django.contrib.auth.handlers.modwsgi.check_password()`.
  3. Submit repeated authentication attempts with candidate usernames and invalid passwords.
  4. Measure response times for each candidate over many trials to reduce network noise.
  5. Statistically compare timing distributions to separate likely valid users from invalid users.
  6. Use the enumerated usernames in follow-on credential attacks, phishing, or account takeover attempts.

How to detect it

To assess prior exploitation, review Apache access logs, error logs, WSGI logs, reverse proxy logs, web application authentication logs, and identity-provider or account-lockout telemetry for repeated failed authentication attempts against `mod_wsgi`-protected resources. Look for a single source or small set of sources submitting many different usernames with failed Basic authentication, especially where each username is attempted repeatedly with a consistent invalid password and no successful login. Timing attacks may appear as steady, scripted request patterns rather than bursts, with many HTTP 401 responses and unusually uniform spacing intended to collect response-time samples. If request duration is logged, compare latency distributions for failed attempts by username and source IP; suspicious activity may show repeated sampling of candidate usernames rather than normal user mistakes. No public exploitation, named threat actors, KEV activity, or ransomware use is currently indicated by the supplied intelligence, so detection should focus on behavioral evidence rather than known malware artifacts.

  • django.contrib.auth.handlers.modwsgi
  • django.contrib.auth.handlers.modwsgi.check_password
  • WSGIAuthUserScript
  • WSGIAuthGroupScript
  • mod_wsgi
  • Authorization: Basic
  • HTTP/1.1" 401
  • 401

What your security team should do

  • Inventory Django applications that use Apache `mod_wsgi` authentication and prioritize internet-facing instances first.
  • Upgrade Django to 6.0.2+, 5.2.11+, or 4.2.28+; migrate unsupported Django branches to a supported fixed release.
  • Check downstream products and source-based deployments, including GitLab source deployments, for bundled or pinned vulnerable Django versions.
  • Enable or tune rate limiting, failed-login monitoring, and alerting for high-volume authentication attempts using many distinct usernames.
  • Review recent authentication logs for username-enumeration behavior before assuming no exploitation occurred.
  • Feed any discovered valid-user enumeration activity into credential-stuffing, password-spraying, and phishing detection workflows.
  • Because this is not currently KEV-listed and has low EPSS, handle through normal vulnerability management unless exposed authentication endpoints are high-value or internet-facing.

The record

An issue was discovered in 6.0 before 6.0.2, 5.2 before 5.2.11, and 4.2 before 4.2.28. The `django.contrib.auth.handlers.modwsgi.check_password()` function for authentication via `mod_wsgi` allows remote attackers to enumerate users via a timing attack. Earlier, unsupported Django series (such as 5.0.x, 4.1.x, and 3.2.x) were not evaluated and may also be affected. Django would like to thank Stackered for reporting this issue.

Affected packages

Ecosystem Package Introduced Fixed
PyPI django 4.2a1 4.2.28
PyPI django 5.2a1 5.2.11
PyPI django 6.0a1 6.0.2
Bitnami django 4.2.0 4.2.28
Chainguard authentik 0 2025.12.1-r2
Chainguard authentik-fips 0 2025.12.1-r2
Chainguard awx 0 24.6.1-r27
Chainguard label-studio 0 1.22.0-r3
Mageia:9 python-django 0 4.1.13-1.10.mga9
SUSE:Linux Enterprise Module for Package Hub 15 SP7 python-Django 0 4.2.11-150600.3.47.1
openSUSE:Leap 15.6 python-Django 0 4.2.11-150600.3.47.1
openSUSE:Leap 16.0 python-Django 0 5.2.4-bp160.5.1
openSUSE:Tumbleweed python-Django 0 5.2.11-1.1
openSUSE:Tumbleweed python-Django4 0 4.2.28-1.1
openSUSE:Tumbleweed python-Django6 0 6.0.2-1.1

Related vulnerabilities