diff options
| author | Jake Howard <git@theorangeone.net> | 2025-11-19 16:52:28 +0000 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2026-02-03 08:13:08 -0500 |
| commit | 184e38ab0a061c365f5775676a074796d8abd02f (patch) | |
| tree | 09ba0f5bade619378df4f260f5697fd833257b62 /tests/auth_tests | |
| parent | d8c551d21459b260f50906f1e48bdf381e620533 (diff) | |
[5.2.x] Fixed CVE-2025-13473 -- Standardized timing of check_password() in mod_wsgi auth handler.
Refs CVE-2024-39329, #20760.
Thanks Stackered for the report, and Jacob Walls and Markus Holtermann
for the reviews.
Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
Backport of 3eb814e02a4c336866d4189fa0c24fd1875863ed from main.
Diffstat (limited to 'tests/auth_tests')
| -rw-r--r-- | tests/auth_tests/test_handlers.py | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/tests/auth_tests/test_handlers.py b/tests/auth_tests/test_handlers.py index a6b53a9ef1..32b4371198 100644 --- a/tests/auth_tests/test_handlers.py +++ b/tests/auth_tests/test_handlers.py @@ -1,4 +1,7 @@ +from unittest import mock + from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user +from django.contrib.auth.hashers import get_hasher from django.contrib.auth.models import Group, User from django.test import TransactionTestCase, override_settings @@ -73,3 +76,28 @@ class ModWsgiHandlerTestCase(TransactionTestCase): self.assertEqual(groups_for_user({}, "test"), [b"test_group"]) self.assertEqual(groups_for_user({}, "test1"), []) + + def test_check_password_fake_runtime(self): + """ + Hasher is run once regardless of whether the user exists. Refs #20760. + """ + User.objects.create_user("test", "test@example.com", "test") + User.objects.create_user("inactive", "test@nono.com", "test", is_active=False) + User.objects.create_user("unusable", "test@nono.com") + + hasher = get_hasher() + + for username, password in [ + ("test", "test"), + ("test", "wrong"), + ("inactive", "test"), + ("inactive", "wrong"), + ("unusable", "test"), + ("doesnotexist", "test"), + ]: + with ( + self.subTest(username=username, password=password), + mock.patch.object(hasher, "encode") as mock_make_password, + ): + check_password({}, username, password) + mock_make_password.assert_called_once() |
