A RetroSearch Logo

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

Search Query:

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

[1.9.x] Fixed CVE-2016-2513 -- Fixed user enumeration timing attack d… · django/django@af7d09b · GitHub

4 4

import binascii

5 5

import hashlib

6 6

import importlib

7 +

import warnings

7 8

from collections import OrderedDict

8 9 9 10

from django.conf import settings

@@ -46,10 +47,17 @@ def check_password(password, encoded, setter=None, preferred='default'):

46 47

preferred = get_hasher(preferred)

47 48

hasher = identify_hasher(encoded)

48 49 49 -

must_update = hasher.algorithm != preferred.algorithm

50 -

if not must_update:

51 -

must_update = preferred.must_update(encoded)

50 +

hasher_changed = hasher.algorithm != preferred.algorithm

51 +

must_update = hasher_changed or preferred.must_update(encoded)

52 52

is_correct = hasher.verify(password, encoded)

53 + 54 +

# If the hasher didn't change (we don't protect against enumeration if it

55 +

# does) and the password should get updated, try to close the timing gap

56 +

# between the work factor of the current encoded password and the default

57 +

# work factor.

58 +

if not is_correct and not hasher_changed and must_update:

59 +

hasher.harden_runtime(password, encoded)

60 + 53 61

if setter and is_correct and must_update:

54 62

setter(password)

55 63

return is_correct

@@ -216,6 +224,19 @@ def safe_summary(self, encoded):

216 224

def must_update(self, encoded):

217 225

return False

218 226 227 +

def harden_runtime(self, password, encoded):

228 +

"""

229 +

Bridge the runtime gap between the work factor supplied in `encoded`

230 +

and the work factor suggested by this hasher.

231 + 232 +

Taking PBKDF2 as an example, if `encoded` contains 20000 iterations and

233 +

`self.iterations` is 30000, this method should run password through

234 +

another 10000 iterations of PBKDF2. Similar approaches should exist

235 +

for any hasher that has a work factor. If not, this method should be

236 +

defined as a no-op to silence the warning.

237 +

"""

238 +

warnings.warn('subclasses of BasePasswordHasher should provide a harden_runtime() method')

239 + 219 240 220 241

class PBKDF2PasswordHasher(BasePasswordHasher):

221 242

"""

@@ -258,6 +279,12 @@ def must_update(self, encoded):

258 279

algorithm, iterations, salt, hash = encoded.split('$', 3)

259 280

return int(iterations) != self.iterations

260 281 282 +

def harden_runtime(self, password, encoded):

283 +

algorithm, iterations, salt, hash = encoded.split('$', 3)

284 +

extra_iterations = self.iterations - int(iterations)

285 +

if extra_iterations > 0:

286 +

self.encode(password, salt, extra_iterations)

287 + 261 288 262 289

class PBKDF2SHA1PasswordHasher(PBKDF2PasswordHasher):

263 290

"""

@@ -308,23 +335,8 @@ def encode(self, password, salt):

308 335

def verify(self, password, encoded):

309 336

algorithm, data = encoded.split('$', 1)

310 337

assert algorithm == self.algorithm

311 -

bcrypt = self._load_library()

312 - 313 -

# Hash the password prior to using bcrypt to prevent password truncation

314 -

# See: https://code.djangoproject.com/ticket/20138

315 -

if self.digest is not None:

316 -

# We use binascii.hexlify here because Python3 decided that a hex encoded

317 -

# bytestring is somehow a unicode.

318 -

password = binascii.hexlify(self.digest(force_bytes(password)).digest())

319 -

else:

320 -

password = force_bytes(password)

321 - 322 -

# Ensure that our data is a bytestring

323 -

data = force_bytes(data)

324 -

# force_bytes() necessary for py-bcrypt compatibility

325 -

hashpw = force_bytes(bcrypt.hashpw(password, data))

326 - 327 -

return constant_time_compare(data, hashpw)

338 +

encoded_2 = self.encode(password, force_bytes(data))

339 +

return constant_time_compare(encoded, encoded_2)

328 340 329 341

def safe_summary(self, encoded):

330 342

algorithm, empty, algostr, work_factor, data = encoded.split('$', 4)

@@ -341,6 +353,16 @@ def must_update(self, encoded):

341 353

algorithm, empty, algostr, rounds, data = encoded.split('$', 4)

342 354

return int(rounds) != self.rounds

343 355 356 +

def harden_runtime(self, password, encoded):

357 +

_, data = encoded.split('$', 1)

358 +

salt = data[:29] # Length of the salt in bcrypt.

359 +

rounds = data.split('$')[2]

360 +

# work factor is logarithmic, adding one doubles the load.

361 +

diff = 2**(self.rounds - int(rounds)) - 1

362 +

while diff > 0:

363 +

self.encode(password, force_bytes(salt))

364 +

diff -= 1

365 + 344 366 345 367

class BCryptPasswordHasher(BCryptSHA256PasswordHasher):

346 368

"""

@@ -388,6 +410,9 @@ def safe_summary(self, encoded):

388 410

(_('hash'), mask_hash(hash)),

389 411

])

390 412 413 +

def harden_runtime(self, password, encoded):

414 +

pass

415 + 391 416 392 417

class MD5PasswordHasher(BasePasswordHasher):

393 418

"""

@@ -416,6 +441,9 @@ def safe_summary(self, encoded):

416 441

(_('hash'), mask_hash(hash)),

417 442

])

418 443 444 +

def harden_runtime(self, password, encoded):

445 +

pass

446 + 419 447 420 448

class UnsaltedSHA1PasswordHasher(BasePasswordHasher):

421 449

"""

@@ -448,6 +476,9 @@ def safe_summary(self, encoded):

448 476

(_('hash'), mask_hash(hash)),

449 477

])

450 478 479 +

def harden_runtime(self, password, encoded):

480 +

pass

481 + 451 482 452 483

class UnsaltedMD5PasswordHasher(BasePasswordHasher):

453 484

"""

@@ -481,6 +512,9 @@ def safe_summary(self, encoded):

481 512

(_('hash'), mask_hash(encoded, show=3)),

482 513

])

483 514 515 +

def harden_runtime(self, password, encoded):

516 +

pass

517 + 484 518 485 519

class CryptPasswordHasher(BasePasswordHasher):

486 520

"""

@@ -515,3 +549,6 @@ def safe_summary(self, encoded):

515 549

(_('salt'), salt),

516 550

(_('hash'), mask_hash(data, show=3)),

517 551

])

552 + 553 +

def harden_runtime(self, password, encoded):

554 +

pass


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