티스토리 수익 글 보기

티스토리 수익 글 보기

[1.11.x] Fixed CVE-2018-6188 — Fixed information leakage in Authenti… · django/django@57b95fe · GitHub
Skip to content

Commit 57b95fe

Browse files
committed
[1.11.x] Fixed CVE-2018-6188 — Fixed information leakage in AuthenticationForm.
Reverted 359370a (refs #28645). This is a security fix.
1 parent 1c9233b commit 57b95fe

File tree

3 files changed

+42
11
lines changed

3 files changed

+42
11
lines changed

django/contrib/auth/forms.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,6 @@ def clean(self):
186186
if username is not None and password:
187187
self.user_cache = authenticate(self.request, username=username, password=password)
188188
if self.user_cache is None:
189-
# An authentication backend may reject inactive users. Check
190-
# if the user exists and is inactive, and raise the 'inactive'
191-
# error if so.
192-
try:
193-
self.user_cache = UserModel._default_manager.get_by_natural_key(username)
194-
except UserModel.DoesNotExist:
195-
pass
196-
else:
197-
self.confirm_login_allowed(self.user_cache)
198189
raise forms.ValidationError(
199190
self.error_messages['invalid_login'],
200191
code='invalid_login',

docs/releases/1.11.10.txt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,28 @@
22
Django 1.11.10 release notes
33
============================
44

5-
*Expected February 1, 2018*
5+
*February 1, 2018*
66

7-
Django 1.11.10 fixes several bugs in 1.11.9.
7+
Django 1.11.10 fixes a security issue and several bugs in 1.11.9.
8+
9+
CVE-2018-6188: Information leakage in ``AuthenticationForm``
10+
============================================================
11+
12+
A regression in Django 1.11.8 made
13+
:class:`~django.contrib.auth.forms.AuthenticationForm` run its
14+
``confirm_login_allowed()`` method even if an incorrect password is entered.
15+
This can leak information about a user, depending on what messages
16+
``confirm_login_allowed()`` raises. If ``confirm_login_allowed()`` isn't
17+
overridden, an attacker enter an arbitrary username and see if that user has
18+
been set to ``is_active=False``. If ``confirm_login_allowed()`` is overridden,
19+
more sensitive details could be leaked.
20+
21+
This issue is fixed with the caveat that ``AuthenticationForm`` can no longer
22+
raise the "This account is inactive." error if the authentication backend
23+
rejects inactive users (the default authentication backend, ``ModelBackend``,
24+
has done that since Django 1.10). This issue will be revisited for Django 2.1
25+
as a fix to address the caveat will likely be too invasive for inclusion in
26+
older versions.
827

928
Bugfixes
1029
========

tests/auth_tests/test_forms.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ def test_password_help_text(self):
249249
)
250250

251251

252+
# To verify that the login form rejects inactive users, use an authentication
253+
# backend that allows them.
254+
@override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.AllowAllUsersModelBackend'])
252255
class AuthenticationFormTest(TestDataMixin, TestCase):
253256

254257
def test_invalid_username(self):
@@ -278,6 +281,24 @@ def test_inactive_user(self):
278281
self.assertFalse(form.is_valid())
279282
self.assertEqual(form.non_field_errors(), [force_text(form.error_messages['inactive'])])
280283

284+
# Use an authentication backend that rejects inactive users.
285+
@override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.ModelBackend'])
286+
def test_inactive_user_incorrect_password(self):
287+
"""An invalid login doesn't leak the inactive status of a user."""
288+
data = {
289+
'username': 'inactive',
290+
'password': 'incorrect',
291+
}
292+
form = AuthenticationForm(None, data)
293+
self.assertFalse(form.is_valid())
294+
self.assertEqual(
295+
form.non_field_errors(), [
296+
form.error_messages['invalid_login'] % {
297+
'username': User._meta.get_field('username').verbose_name
298+
}
299+
]
300+
)
301+
281302
def test_login_failed(self):
282303
signal_calls = []
283304

0 commit comments

Comments
 (0)