Cách Django quản lý và bảo vệ mật khẩu (P2)
Sử dụng scrypt trong Django:
Scrypt tương tự như PBKDF2 và bcrypt trong việc sử dụng một số lần lặp lại để làm chậm các cuộc tấn công brute-force. Tuy nhiên, vì PBKDF2 và bcrypt không yêu cầu nhiều bộ nhớ, những kẻ tấn công có đủ nguồn lực có thể phát động các cuộc tấn công song song quy mô lớn để đẩy nhanh quá trình tấn công. Scrypt được thiết kế đặc biệt để sử dụng nhiều bộ nhớ hơn so với các hàm dẫn xuất khóa dựa trên mật khẩu khác nhằm hạn chế số lượng mà kẻ tấn công có thể sử dụng.
Để sử dụng scrypt làm thuật toán lưu trữ thì làm như sau:
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.ScryptPasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]
Nâng cấp mật khẩu:
Khi người dùng đăng nhập, nếu mật khẩu của họ được lưu trữ bằng bất kỳ thứ gì khác ngoài thuật toán ưu tiên, Django sẽ tự động nâng cấp. Điều này có nghĩa là các bản cài đặt cũ của Django sẽ tự động được bảo vệ khi người dùng đăng nhập và điều đó cũng có nghĩa là bạn có thể chuyển sang các thuật toán lưu trữ mới khi chúng được được đưa vào sử dụng.
Tuy nhiên, Django chỉ có thể nâng cấp mật khẩu sử dụng các thuật toán được đề cập trong PASSWORD_HASHERS
, vì vậy khi nâng cấp lên hệ thống mới, bạn nên đảm bảo không bao giờ xóa các mục khỏi PASSWORD_HASHERS
. Nếu bạn làm vậy, người dùng sử dụng các thuật toán chưa được đề cập sẽ không thể nâng cấp. Mật khẩu băm sẽ được cập nhật khi tăng (hoặc giảm) số lần lặp lại PBKDF2, vòng bcrypt hoặc thuộc tính argon2.
Lưu ý rằng nếu tất cả mật khẩu trong cơ sở dữ liệu của bạn không được mã hóa trong thuật toán của trình băm mặc định, bạn có thể dễ bị tấn công định thời gian liệt kê người dùng do sự khác biệt giữa thời lượng yêu cầu đăng nhập cho người dùng có mật khẩu được mã hóa trong thuật toán không mặc định và thời lượng yêu cầu đăng nhập cho người dùng không tồn tại (chạy bộ băm mặc định). Bạn có thể giảm thiểu điều này bằng cách nâng cấp các hàm băm mật khẩu cũ hơn .
Các hàm băm:
Nếu hiện tại bạn có cơ sở dữ liệu với hàm băm yếu và cũ như MD5 hoặc SHA1, bạn có thể muốn tự mình nâng cấp các hàm băm đó thay vì đợi quá trình nâng cấp xảy ra khi người dùng đăng nhập. Trong trường hợp này, bạn có thể sử dụng bộ băm mật khẩu "wrapped":
Đầu tiên, ta sẽ thêm trình băm tùy chỉnh lên accounts/hashers.py
:
from django.contrib.auth.hashers import (
PBKDF2PasswordHasher, SHA1PasswordHasher,
)
class PBKDF2WrappedSHA1PasswordHasher(PBKDF2PasswordHasher):
algorithm = 'pbkdf2_wrapped_sha1'
def encode_sha1_hash(self, sha1_hash, salt, iterations=None):
return super().encode(sha1_hash, salt, iterations)
def encode(self, password, salt, iterations=None):
_, _, sha1_hash = SHA1PasswordHasher().encode(password, salt).split('$', 2)
return self.encode_sha1_hash(sha1_hash, salt, iterations)
accounts/migrations/0002_migrate_sha1_password.py
from django.db import migrations
from ..hashers import PBKDF2WrappedSHA1PasswordHasher
def forwards_func(apps, schema_editor):
User = apps.get_model('auth', 'User')
users = User.objects.filter(password__startswith='sha1$')
hasher = PBKDF2WrappedSHA1PasswordHasher()
for user in users:
algorithm, salt, sha1_hash = user.password.split('$', 2)
user.password = hasher.encode_sha1_hash(sha1_hash, salt)
user.save(update_fields=['password'])
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
# replace this with the latest migration in contrib.auth
('auth', '####_migration_name'),
]
operations = [
migrations.RunPython(forwards_func),
]
Danh sách đầy đủ các hàm băm có trong Django là:
[
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.ScryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher',
'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
]
Nguồn: django tuitorial