Xóa mật khẩu người dùng


98

Làm cách nào để thoát hoặc xóa mật khẩu do người dùng cung cấp trước khi băm và lưu trữ chúng trong cơ sở dữ liệu của mình?

Khi các nhà phát triển PHP xem xét việc băm mật khẩu của người dùng cho mục đích bảo mật, họ thường có xu hướng nghĩ về những mật khẩu đó giống như bất kỳ dữ liệu nào khác do người dùng cung cấp. Chủ đề này thường xuất hiện trong các câu hỏi PHP liên quan đến lưu trữ mật khẩu; các nhà phát triển thường muốn làm sạch mật khẩu sử dụng các chức năng như escape_string()(trong lặp khác nhau), htmlspecialchars(), addslashes()và những người khác trước khi băm nó và lưu trữ nó trong cơ sở dữ liệu.


1
bạn có thể mã hóa base64 của người dùng
MSS

Không có @MSS, bạn không nên vì base64 đang mã hóa chứ không phải mã hóa hoặc băm . Mật khẩu phải luôn được băm .
Jay Blanchard

1
Ý tôi là trước khi băm;)
MSS

Bạn không nên và không cần phải làm điều đó trước khi băm. Nó sẽ khiến bạn phải viết mã bổ sung không cần thiết @MSS
Jay Blanchard

Câu trả lời:


99

Bạn không bao giờ được thoát, cắt hoặc sử dụng bất kỳ cơ chế làm sạch nào khác trên mật khẩu mà bạn sẽ băm bằng PHP password_hash()vì một số lý do, trong đó lý do lớn nhất là vì việc làm sạch thêm mật khẩu yêu cầu mã bổ sung không cần thiết.

Bạn sẽ lập luận (và bạn thấy điều đó trong mọi bài đăng mà dữ liệu người dùng được chấp nhận sử dụng trong hệ thống của bạn) rằng chúng tôi nên xóa tất cả thông tin người dùng nhập và bạn sẽ đúng đối với mọi thông tin khác mà chúng tôi chấp nhận từ người dùng của mình. Mật khẩu là khác nhau. Mật khẩu băm không thể cung cấp bất kỳ mối đe dọa tiêm SQL nào vì chuỗi được chuyển thành băm trước khi lưu trữ trong cơ sở dữ liệu.

Hành động băm mật khẩu là hành động làm cho mật khẩu được lưu trữ an toàn trong cơ sở dữ liệu của bạn. Hàm băm không mang lại ý nghĩa đặc biệt cho bất kỳ byte nào, vì vậy không cần làm sạch đầu vào của nó vì lý do bảo mật

Nếu bạn tuân theo các câu thần chú về việc cho phép người dùng sử dụng mật khẩu / cụm từ mà họ mong muốn và bạn không giới hạn mật khẩu , thì việc cho phép bất kỳ độ dài nào, bất kỳ số lượng khoảng trắng nào và bất kỳ ký tự đặc biệt nào được băm sẽ giúp mật khẩu / cụm mật khẩu an toàn bất kể nội dung nào được chứa bên trong Mật khẩu. Kể từ bây giờ, hàm băm phổ biến nhất (mặc định), PASSWORD_BCRYPThãy biến mật khẩu thành một chuỗi rộng 60 ký tự chứa muối ngẫu nhiên cùng với thông tin mật khẩu được băm và chi phí (chi phí thuật toán để tạo hàm băm):

PASSWORD_BCRYPT được sử dụng để tạo hàm băm mật khẩu mới bằng thuật toán CRYPT_BLOWFISH. Điều này sẽ luôn dẫn đến một hàm băm sử dụng định dạng crypt "$ 2y $", luôn có độ rộng 60 ký tự.

Các yêu cầu về không gian để lưu trữ hàm băm có thể thay đổi khi các phương pháp băm khác nhau được thêm vào hàm, vì vậy tốt hơn hết là bạn nên mở rộng loại cột cho hàm băm được lưu trữ, chẳng hạn như VARCHAR(255)hoặc TEXT.

Bạn có thể sử dụng một truy vấn SQL hoàn chỉnh làm mật khẩu của mình và nó sẽ được băm, làm cho nó không thể giải được bằng công cụ SQL, ví dụ:

SELECT * FROM `users`;

Có thể được băm thành $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G

Hãy xem các phương pháp khử trùng khác nhau ảnh hưởng đến mật khẩu như thế nào -

Mật khẩu là I'm a "dessert topping" & a <floor wax>!(Có 5 khoảng trắng ở cuối mật khẩu không được hiển thị ở đây.)

Khi chúng tôi áp dụng các phương pháp cắt tỉa sau đây, chúng tôi nhận được một số kết quả khác nhau:

var_dump(trim($_POST['upassword']));
var_dump(htmlentities($_POST['upassword']));
var_dump(htmlspecialchars($_POST['upassword']));
var_dump(addslashes($_POST['upassword']));
var_dump(strip_tags($_POST['upassword']));

Các kết quả:

string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missing
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // double quotes, ampersand and braces have been changed
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // same here
string(48) "I\'m a \"dessert topping\" & a <floor wax>!     " // escape characters have been added
string(34) "I'm a "dessert topping" & a !     " // looks like we have something missing

Điều gì xảy ra khi chúng tôi gửi những thứ này đến password_hash()? Tất cả chúng đều được băm, giống như truy vấn đã làm ở trên. Vấn đề xảy ra khi bạn cố gắng xác minh mật khẩu. Nếu chúng tôi sử dụng một hoặc nhiều phương pháp này, chúng tôi phải sử dụng lại chúng trước khi so sánh với chúng password_verify(). Những điều sau sẽ không thành công:

password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query

Bạn sẽ phải chạy mật khẩu đã đăng thông qua phương pháp làm sạch bạn đã chọn trước khi sử dụng kết quả của việc đó trong xác minh mật khẩu. Đây là một tập hợp các bước không cần thiết và sẽ làm cho việc băm không tốt hơn.


Sử dụng phiên bản PHP nhỏ hơn 5.5? Bạn có thể sử dụng password_hash() gói tương thích .

Bạn thực sự không nên sử dụng băm mật khẩu MD5 .


13
Không. Nếu anh ấy tạo mật khẩu của mình bằng dấu cách ở cuối, được cho phép, anh ấy phải sử dụng chúng khi đăng nhập @DanBracuk
Jay Blanchard

12
Làm thế nào vậy @DanBracuk? Nếu chúng tôi cho phép người dùng thiết lập mật khẩu mà họ mong muốn, bao gồm cả dấu cách ở đầu / cuối?
Jay Blanchard

16
Đó là lý do tại sao hầu hết mọi thứ đều yêu cầu bạn nhập mật khẩu đã chọn hai lần. Nếu người dùng vô tình thêm các khoảng trắng, họ sẽ tìm ra nó trước khi tiếp tục. Nếu người dùng cố ý làm điều đó thì đó không phải là vấn đề.
Tôi đã đấu vật với một con gấu một lần.

4
@MargaretBloom, một quy tắc ngón tay cái chỉ là một sự khám phá. Đôi khi chúng ta vẫn cần phải suy nghĩ thấu đáo mọi thứ, chẳng hạn như mật khẩu. Bạn nói "không ai biết mọi thứ sẽ thay đổi như thế nào trong tương lai", nhưng có vẻ như nếu bất cứ điều gì sẽ thay đổi, đó là cách chúng ta thoát dữ liệu trước khi đưa vào cơ sở dữ liệu, trong trường hợp đó người dùng sẽ thấy mình bị khóa khi mật khẩu của họ không. còn khớp với những gì chúng tôi đã lưu trữ. Nguy hiểm khi không thoát hàm băm mật khẩu so với nguy cơ thoát chúng là gì?
DavidS

3
Chính xác: tất nhiên bạn sẽ "thoát hàm băm" theo nghĩa giới hạn là chuyển nó một cách chính xác đến một truy vấn SQL được tham số hóa, trong đó một số mã trong trình kết nối SQL của bạn có thể hoặc không làm bất cứ điều gì với nó tương ứng với "thoát", bạn không t biết và không quan tâm. Bạn sẽ không phải viết bất kỳ mã cụ thể nào để đạt được điều đó, bởi vì nó hoàn toàn là thói quen cho tất cả các truy vấn SQL của bạn trừ khi trước đó bạn đã đưa ra một số quyết định sai lầm trong cuộc sống.
Steve Jessop

36

Trước khi băm mật khẩu, bạn nên chuẩn hóa nó như được mô tả trong phần 4 của RFC 7613 . Đặc biệt:

  1. Quy tắc ánh xạ bổ sung: Mọi trường hợp của không gian không phải ASCII PHẢI được ánh xạ tới không gian ASCII (U + 0020); khoảng trắng không phải ASCII là bất kỳ điểm mã Unicode nào có danh mục chung Unicode là "Zs" (ngoại trừ U + 0020).

và:

  1. Quy tắc chuẩn hóa: Mẫu chuẩn hóa Unicode C (NFC) PHẢI được áp dụng cho tất cả các ký tự.

Điều này cố gắng đảm bảo rằng nếu người dùng nhập cùng một mật khẩu nhưng sử dụng phương thức nhập khác, thì mật khẩu đó vẫn phải được chấp nhận.


3
@DavidS, Một Mac Book Bắc Mỹ siêu sáng bóng (mà Joe đã sử dụng ngay trước khi rời đi) và một máy tính quán cà phê internet Đài Loan đã được quốc tế hóa kém (Joe đang cố gắng sử dụng để tải xuống là thẻ lên máy bay trở lại).
Margaret Bloom

2
Nghe có vẻ jingoistic. :-) Xin cảm ơn.
DavidS

3
Hừ! Nếu bạn làm điều này, thì bạn cũng nên xác thực mật khẩu để từ chối bất kỳ mật khẩu nào chứa các ký tự chưa được gán. Sẽ thật khủng khiếp nếu người dùng sử dụng KHÔNG GIAN ĐÃ ĐƯỢC GIAO LƯU mà ứng dụng của bạn không nhận ra và do đó băm như hiện tại, sau đó bạn nâng cấp Cơ sở dữ liệu ký tự Unicode của mình và đột nhiên KHÔNG GIAN MỚI ĐƯỢC ánh xạ tới KHÔNG GIAN trước khi băm, như vậy (các) anh ta không còn có thể nhập mật khẩu mà ứng dụng của bạn sẽ băm thành hàm băm cũ.
ruakh

4
@JayBlanchard Vì khi bạn nhấn phím cách trên một máy và khi nhấn vào máy khác, bạn có thể nhận được hai điểm mã Unicode khác nhau và chúng sẽ có hai bảng mã UTF-8 khác nhau mà người dùng không nhận biết được gì. Có thể lập luận rằng đây là một vấn đề mà bạn muốn bỏ qua, nhưng RFC 7613 được sinh ra từ các vấn đề thực tế như vậy, đó không phải là một khuyến nghị thực tế.
Phục hồi Monica

1
@ruakh Khi bạn quyết định xử lý mật khẩu theo một cách nhất định, chúng phải được tiếp tục xử lý theo cách đó, nếu không mọi thứ sẽ bị hỏng đối với các trường hợp sử dụng hiện có. Nếu bạn có ý định thay đổi phương pháp tiền xử lý trong tương lai, bạn nên lưu trữ nó cùng với biểu diễn mật khẩu đã được xử lý trước và băm. Theo cách đó, khi bạn nhận được thông tin đầu vào, bạn chọn phương pháp tiền xử lý / băm dựa trên những gì bạn đang so sánh với.
Phục hồi Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.