A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/django/django/commit/302a4ff1e8b1c798aab97673909c7a3dfda42c26 below:

[3.0.x] Fixed CVE-2019-19844 -- Used verified user email for password… · django/django@302a4ff · GitHub

File tree Expand file treeCollapse file tree 5 files changed

+110

-10

lines changed

Filter options

Expand file treeCollapse file tree 5 files changed

+110

-10

lines changed Original file line number Diff line number Diff line change

@@ -20,6 +20,15 @@

20 20

UserModel = get_user_model()

21 21 22 22 23 +

def _unicode_ci_compare(s1, s2):

24 +

"""

25 +

Perform case-insensitive comparison of two identifiers, using the

26 +

recommended algorithm from Unicode Technical Report 36, section

27 +

2.11.2(B)(2).

28 +

"""

29 +

return unicodedata.normalize('NFKC', s1).casefold() == unicodedata.normalize('NFKC', s2).casefold()

30 + 31 + 23 32

class ReadOnlyPasswordHashWidget(forms.Widget):

24 33

template_name = 'auth/widgets/read_only_password_hash.html'

25 34

read_only = True

@@ -269,11 +278,16 @@ def get_users(self, email):

269 278

that prevent inactive users and users with unusable passwords from

270 279

resetting their password.

271 280

"""

281 +

email_field_name = UserModel.get_email_field_name()

272 282

active_users = UserModel._default_manager.filter(**{

273 -

'%s__iexact' % UserModel.get_email_field_name(): email,

283 +

'%s__iexact' % email_field_name: email,

274 284

'is_active': True,

275 285

})

276 -

return (u for u in active_users if u.has_usable_password())

286 +

return (

287 +

u for u in active_users

288 +

if u.has_usable_password() and

289 +

_unicode_ci_compare(email, getattr(u, email_field_name))

290 +

)

277 291 278 292

def save(self, domain_override=None,

279 293

subject_template_name='registration/password_reset_subject.txt',

@@ -286,15 +300,17 @@ def save(self, domain_override=None,

286 300

user.

287 301

"""

288 302

email = self.cleaned_data["email"]

303 +

email_field_name = UserModel.get_email_field_name()

289 304

for user in self.get_users(email):

290 305

if not domain_override:

291 306

current_site = get_current_site(request)

292 307

site_name = current_site.name

293 308

domain = current_site.domain

294 309

else:

295 310

site_name = domain = domain_override

311 +

user_email = getattr(user, email_field_name)

296 312

context = {

297 -

'email': email,

313 +

'email': user_email,

298 314

'domain': domain,

299 315

'site_name': site_name,

300 316

'uid': urlsafe_base64_encode(force_bytes(user.pk)),

@@ -305,7 +321,7 @@ def save(self, domain_override=None,

305 321

}

306 322

self.send_mail(

307 323

subject_template_name, email_template_name, context, from_email,

308 -

email, html_email_template_name=html_email_template_name,

324 +

user_email, html_email_template_name=html_email_template_name,

309 325

)

310 326 311 327 Original file line number Diff line number Diff line change

@@ -2,9 +2,25 @@

2 2

Django 1.11.27 release notes

3 3

============================

4 4 5 -

*Expected January 2, 2020*

5 +

*December 18, 2019*

6 6 7 -

Django 1.11.27 fixes a data loss bug in 1.11.26.

7 +

Django 1.11.27 fixes a security issue and a data loss bug in 1.11.26.

8 + 9 +

CVE-2019-19844: Potential account hijack via password reset form

10 +

================================================================

11 + 12 +

By submitting a suitably crafted email address making use of Unicode

13 +

characters, that compared equal to an existing user email when lower-cased for

14 +

comparison, an attacker could be sent a password reset token for the matched

15 +

account.

16 + 17 +

In order to avoid this vulnerability, password reset requests now compare the

18 +

submitted email using the stricter, recommended algorithm for case-insensitive

19 +

comparison of two identifiers from `Unicode Technical Report 36, section

20 +

2.11.2(B)(2)`__. Upon a match, the email containing the reset token will be

21 +

sent to the email address on record rather than the submitted address.

22 + 23 +

.. __: https://www.unicode.org/reports/tr36/#Recommendations_General

8 24 9 25

Bugfixes

10 26

========

Original file line number Diff line number Diff line change

@@ -2,9 +2,25 @@

2 2

Django 2.2.9 release notes

3 3

==========================

4 4 5 -

*Expected January 2, 2020*

5 +

*December 18, 2019*

6 6 7 -

Django 2.2.9 fixes a data loss bug in 2.2.8.

7 +

Django 2.2.9 fixes a security issue and a data loss bug in 2.2.8.

8 + 9 +

CVE-2019-19844: Potential account hijack via password reset form

10 +

================================================================

11 + 12 +

By submitting a suitably crafted email address making use of Unicode

13 +

characters, that compared equal to an existing user email when lower-cased for

14 +

comparison, an attacker could be sent a password reset token for the matched

15 +

account.

16 + 17 +

In order to avoid this vulnerability, password reset requests now compare the

18 +

submitted email using the stricter, recommended algorithm for case-insensitive

19 +

comparison of two identifiers from `Unicode Technical Report 36, section

20 +

2.11.2(B)(2)`__. Upon a match, the email containing the reset token will be

21 +

sent to the email address on record rather than the submitted address.

22 + 23 +

.. __: https://www.unicode.org/reports/tr36/#Recommendations_General

8 24 9 25

Bugfixes

10 26

========

Original file line number Diff line number Diff line change

@@ -2,9 +2,25 @@

2 2

Django 3.0.1 release notes

3 3

==========================

4 4 5 -

*Expected January 2, 2020*

5 +

*December 18, 2019*

6 6 7 -

Django 3.0.1 fixes several bugs in 3.0.

7 +

Django 3.0.1 fixes a security issue and several bugs in 3.0.

8 + 9 +

CVE-2019-19844: Potential account hijack via password reset form

10 +

================================================================

11 + 12 +

By submitting a suitably crafted email address making use of Unicode

13 +

characters, that compared equal to an existing user email when lower-cased for

14 +

comparison, an attacker could be sent a password reset token for the matched

15 +

account.

16 + 17 +

In order to avoid this vulnerability, password reset requests now compare the

18 +

submitted email using the stricter, recommended algorithm for case-insensitive

19 +

comparison of two identifiers from `Unicode Technical Report 36, section

20 +

2.11.2(B)(2)`__. Upon a match, the email containing the reset token will be

21 +

sent to the email address on record rather than the submitted address.

22 + 23 +

.. __: https://www.unicode.org/reports/tr36/#Recommendations_General

8 24 9 25

Bugfixes

10 26

========

Original file line number Diff line number Diff line change

@@ -804,6 +804,42 @@ def test_invalid_email(self):

804 804

self.assertFalse(form.is_valid())

805 805

self.assertEqual(form['email'].errors, [_('Enter a valid email address.')])

806 806 807 +

def test_user_email_unicode_collision(self):

808 +

User.objects.create_user('mike123', 'mike@example.org', 'test123')

809 +

User.objects.create_user('mike456', 'mıke@example.org', 'test123')

810 +

data = {'email': 'mıke@example.org'}

811 +

form = PasswordResetForm(data)

812 +

self.assertTrue(form.is_valid())

813 +

form.save()

814 +

self.assertEqual(len(mail.outbox), 1)

815 +

self.assertEqual(mail.outbox[0].to, ['mıke@example.org'])

816 + 817 +

def test_user_email_domain_unicode_collision(self):

818 +

User.objects.create_user('mike123', 'mike@ixample.org', 'test123')

819 +

User.objects.create_user('mike456', 'mike@ıxample.org', 'test123')

820 +

data = {'email': 'mike@ıxample.org'}

821 +

form = PasswordResetForm(data)

822 +

self.assertTrue(form.is_valid())

823 +

form.save()

824 +

self.assertEqual(len(mail.outbox), 1)

825 +

self.assertEqual(mail.outbox[0].to, ['mike@ıxample.org'])

826 + 827 +

def test_user_email_unicode_collision_nonexistent(self):

828 +

User.objects.create_user('mike123', 'mike@example.org', 'test123')

829 +

data = {'email': 'mıke@example.org'}

830 +

form = PasswordResetForm(data)

831 +

self.assertTrue(form.is_valid())

832 +

form.save()

833 +

self.assertEqual(len(mail.outbox), 0)

834 + 835 +

def test_user_email_domain_unicode_collision_nonexistent(self):

836 +

User.objects.create_user('mike123', 'mike@ixample.org', 'test123')

837 +

data = {'email': 'mike@ıxample.org'}

838 +

form = PasswordResetForm(data)

839 +

self.assertTrue(form.is_valid())

840 +

form.save()

841 +

self.assertEqual(len(mail.outbox), 0)

842 + 807 843

def test_nonexistent_email(self):

808 844

"""

809 845

Test nonexistent email address. This should not fail because it would

You can’t perform that action at this time.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4