CVE-2024-45231
NoneCVSS
—
EPSS
0.8%
Published
Oct 8, 2024
CISA due date
—
Cloudanix analysis
A flaw in some Django password reset pages can let outsiders figure out which email addresses have accounts if the site’s email sending is failing.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Moderate
- Impact
- Data Exposure
- Component
- Web Framework
- Class
- Information Disclosure
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
CVE-2024-45231 is an information disclosure flaw in Django’s django.contrib.auth.forms.PasswordResetForm as shipped in Django 5.1.1, 5.0.9, and 4.2.16. In applications that use this form in a password-reset view, remote unauthenticated users may be able to distinguish whether a submitted email address belongs to an existing user when outbound email delivery consistently fails. The flaw does not directly expose passwords or allow account takeover by itself, but it can disclose valid account identifiers that can be reused for phishing, credential stuffing, social engineering, or targeted password attacks.
Why it matters to the business
Organizations running affected Django versions may unintentionally reveal which email addresses have accounts in their applications during password reset attempts. This can increase the risk of targeted phishing, credential stuffing, privacy complaints, and regulatory exposure where account membership is sensitive. The EPSS score is low and there is no CISA KEV listing or known ransomware association, so this is generally a lower-urgency vulnerability than direct code execution or authentication bypass issues; however, internet-facing applications with sensitive user populations should still prioritize remediation because enumeration weaknesses are easy to automate at scale.
How an attack unfolds
An attacker identifies an application using Django’s built-in password reset flow or a view based on django.contrib.auth.forms.PasswordResetForm. The attacker submits password reset requests for a list of candidate email addresses. Under normal secure behavior, the application should respond indistinguishably whether or not the account exists. In the vulnerable condition, when email sending is consistently failing, the password reset handling can produce observably different outcomes depending on whether the submitted address matches an existing user. The attacker compares response status codes, response bodies, redirects, timing, or error behavior to infer valid user email addresses. The resulting list can then be used for follow-on attacks such as phishing, password spraying, credential stuffing, or privacy-invasive profiling.
How to fix it
Upgrade Django to a version containing the upstream fix for PasswordResetForm. For source-based deployments of django/django, update to a revision containing commit 6f9fea33137fee6416ff43b775aa9567440a23d3 or later. Ensure packaged Django dependencies are upgraded to the corresponding vendor release that includes this fix. As defense in depth, make password reset responses uniform regardless of whether the email exists or whether email delivery succeeds, avoid exposing backend mail errors to users, log mail delivery failures server-side only, and apply rate limiting, CAPTCHA or abuse controls, and monitoring to password reset endpoints.
How to confirm the fix worked
Confirm the deployed Django version or source revision includes the fix, specifically commit 6f9fea33137fee6416ff43b775aa9567440a23d3 or a later patched release. Review dependency lockfiles, container images, and runtime package versions to ensure affected versions 5.1.1, 5.0.9, and 4.2.16 are not in use. Test the password reset flow by submitting requests for both existing and non-existing email addresses while simulating email delivery failure; responses should be indistinguishable in status code, body content, redirects, and user-visible error handling. Verify that email backend exceptions are not exposed to unauthenticated users and that password reset attempts are rate-limited and logged.
Typical attack path
- Locate an internet-facing Django application with a password reset endpoint.
- Send password reset requests using known or guessed email addresses.
- Observe response differences when outbound email delivery is failing, such as errors, redirects, status codes, messages, or timing changes.
- Classify email addresses as likely valid or invalid based on the observed behavior.
- Use enumerated valid addresses for targeted phishing, credential stuffing, password spraying, or social engineering.
How to detect it
Review web access logs, application logs, authentication logs, and mail delivery/error logs for evidence of password reset enumeration. Focus on periods when outbound email sending was failing or intermittently unavailable, because the vulnerability depends on consistent email delivery failure producing observable differences. Look for repeated unauthenticated POST requests to password reset endpoints, high numbers of distinct submitted email addresses, sequential or dictionary-style email attempts, unusual spikes in reset requests from a single IP address or user agent, and correlation with SMTP/backend mail exceptions. Compare application responses for reset requests during mail failures to determine whether different status codes, redirects, or error messages were returned for valid versus invalid addresses. Also monitor downstream activity against potentially enumerated users, such as increased failed logins, password spraying patterns, phishing reports, or MFA challenge spikes.
- POST /password_reset/
- POST /accounts/password_reset/
- POST /accounts/password/reset/
- POST /registration/password_reset/
- PasswordResetForm
- SMTPException
- smtplib.SMTPException
- SMTPConnectError
- SMTPServerDisconnected
- SMTPAuthenticationError
- ConnectionRefusedError
- [Errno 111] Connection refused
- [Errno 110] Connection timed out
- Failed to send password reset email
- password reset
What your security team should do
- Inventory applications using Django password reset flows, especially those exposing password reset endpoints to the internet.
- Upgrade affected Django deployments to a patched version or source revision containing commit 6f9fea33137fee6416ff43b775aa9567440a23d3 or later.
- Prioritize applications where account membership is sensitive, such as healthcare, financial, employee, government, or high-profile consumer services.
- Review password reset views for uniform responses and ensure backend email delivery failures are not reflected in user-visible behavior.
- Add or tune rate limiting, bot detection, and alerting for high-volume password reset attempts from the same IP, ASN, user agent, or email pattern.
- Search historical logs for password reset enumeration patterns, especially bursts involving many distinct email addresses and concurrent mail delivery failures.
- Monitor for follow-on activity against enumerated accounts, including password spraying, credential stuffing, phishing reports, and suspicious login failures.
The record
An issue was discovered in Django v5.1.1, v5.0.9, and v4.2.16. The django.contrib.auth.forms.PasswordResetForm class, when used in a view implementing password reset flows, allows remote attackers to enumerate user e-mail addresses by sending password reset requests and observing the outcome (only when e-mail sending is consistently failing).
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| PyPI | django | 0 | 4.2.16 |
| PyPI | django | 5.0 | 5.0.9 |
| PyPI | django | 5.1 | 5.1.1 |
| Bitnami | django | 4.2.0 | 4.2.16 |
| Debian:11 | python-django | 0 | No fix |
| Debian:12 | python-django | 0 | No fix |
| Debian:13 | python-django | 0 | 3:4.2.16-1 |
| Debian:14 | python-django | 0 | 3:4.2.16-1 |
| Mageia:9 | python-django | 0 | 4.1.13-1.2.mga9 |
| SUSE:Linux Enterprise Module for Package Hub 15 SP6 | python-Django | 0 | 4.2.11-150600.3.9.1 |
| SUSE:Package Hub 15 SP5 | python-Django | 0 | 2.2.28-bp155.7.18.1 |
| Ubuntu:20.04:LTS | python-django | 0 | 2:2.2.12-1ubuntu0.25 |
| Ubuntu:22.04:LTS | python-django | 0 | 2:3.2.12-2ubuntu1.14 |
| Ubuntu:24.04:LTS | python-django | 0 | 3:4.2.11-1ubuntu1.3 |
| Ubuntu:24.10 | python-django | 0 | 3:4.2.15-1ubuntu1 |
| Ubuntu:25.04 | python-django | 0 | 3:4.2.15-1ubuntu1 |
| Ubuntu:Pro:14.04:LTS | python-django | 0 | No fix |
| Ubuntu:Pro:16.04:LTS | python-django | 0 | No fix |
| Ubuntu:Pro:18.04:LTS | python-django | 0 | 1:1.11.11-1ubuntu1.21+esm7 |
| openSUSE:Leap 15.5 | python-Django | 0 | 2.0.7-150000.1.33.1 |
| openSUSE:Leap 15.5 | python-Django | 0 | 2.2.28-bp155.7.18.1 |
| openSUSE:Leap 15.6 | python-Django | 0 | 4.2.11-150600.3.9.1 |
| openSUSE:Tumbleweed | python-Django | 0 | 5.1.1-1.1 |
| openSUSE:Tumbleweed | python-Django4 | 0 | 4.2.16-1.1 |
| openSUSE:Tumbleweed | python-Django6 | 0 | 6.0-1.1 |
| pypi | Django | 5.0 | No fix |
| pypi | Django | 5.1 | 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