2010-05-03 32 views
6

Dòng chảy bình thường để đặt lại mật khẩu của người dùng qua đường bưu điện là:Password reset bằng email mà không một bảng cơ sở dữ liệu

  1. Tạo một chuỗi ngẫu nhiên và lưu trữ nó trong một bảng cơ sở dữ liệu
  2. chuỗi Email để sử dụng
  3. Nhấp chuột vào liên kết có chứa chuỗi
  4. Chuỗi được xác thực đối với cơ sở dữ liệu; nếu nó khớp với, pw của người dùng được đặt lại

Tuy nhiên, việc duy trì bảng và hết hạn chuỗi cũ vv có vẻ như một chút rắc rối không cần thiết. Có bất kỳ sai sót rõ ràng trong phương pháp thay thế này?

  1. Tạo một hash MD5 của mật khẩu hiện tại của người dùng
  2. chuỗi Email băm để sử dụng
  3. Người dùng nhấp vào liên kết chứa chuỗi
  4. Chuỗi được xác nhận bằng cách băm pw hiện một lần nữa; nếu nó khớp, pw của người dùng được đặt lại

Lưu ý rằng mật khẩu của người dùng đã được lưu trữ dưới dạng băm và muối, và tôi chỉ băm một lần nữa để nhận chuỗi duy nhất nhưng có thể lặp lại.

Và có, có một "lỗ hổng" rõ ràng: liên kết đặt lại do đó được tạo sẽ không hết hạn cho đến khi người dùng thay đổi mật khẩu của họ (nhấp vào liên kết). Tôi không thực sự thấy lý do tại sao điều này sẽ là một vấn đề mặc dù - nếu hộp thư bị xâm nhập, người sử dụng là hơi say anyway. Và không có nguy cơ tái sử dụng, vì khi mật khẩu của người dùng bị thay đổi, liên kết đặt lại sẽ không còn khớp nữa.

+1

+1 cho ý tưởng thú vị –

Trả lời

8

Để khắc phục obvious flaw, thêm ngày hiện tại (và nhiều thông tin liên quan đến thời gian hơn đại diện cho phần hiện tại của ngày nếu ngay cả một ngày quá dài) với những gì bạn đang băm để tạo chuỗi bí ẩn và kiểm tra nó - điều này làm cho chuỗi "hết hạn" (bạn có thể kiểm tra trước cũng như ngày hoặc phần hiện tại nếu bạn muốn còn "hết hạn"). Vì vậy, có vẻ như với tôi rằng kế hoạch của bạn là khá khả thi.

+0

Ah bạn đã đánh tôi với nó;). Chỉ cần đảm bảo sử dụng dữ liệu tùy thuộc vào người dùng Múi giờ :) –

+0

Làm thế nào để bạn lấy được ngày hết hạn từ người dùng đã gửi băm để kiểm tra xem ngày hiện tại đã qua chưa? Nó sẽ phải được mã hóa và giải quyết. Nếu không: A) Bạn chỉ cần mã hóa nó, người dùng phá vỡ mã hóa, đánh bại mục đích thậm chí có kiểm tra thời gian. B) Bạn để nó như là bản rõ, cùng một thứ. Sau đó, một lần nữa nếu bạn có một số bí mật toàn cầu S để tránh lãng phí không gian, bạn có thể gửi cho người dùng 'HASH (S | | time || userpass)', 'time'; Người dùng gửi lại 'hash',' time', cho phép máy chủ kiểm tra 'HASH (S || time_user_sent_back || userpass)' đối với giá trị băm mà người dùng gửi lại. –

+2

@Longpoke, nếu (ví dụ) chuỗi được cho là hợp lệ vào '2010/05/06' và '2010/05/07', bạn nối thêm' 2010/05/06' vào chuỗi bạn đang băm - đó là nó. Khi kiểm tra, bạn kiểm tra các băm bạn nhận được bằng cách thêm các định dạng ISO của ngày hôm nay và ngày hôm qua - đó là nó, hầu như không khoa học tên lửa. Nếu bạn muốn chi tiết hơn một ngày cho các mục đích hết hạn chuỗi đặc biệt, thì bạn cũng sử dụng _fraction thích hợp của một ngày_ - ví dụ: nếu bạn muốn chuỗi kéo dài khoảng 1,5 ngày, hãy sử dụng "nửa ngày" (ví dụ: AM hoặc PM) trong số những gì bạn đang băm (và kiểm tra 3 khả năng) - cũng không khó! –

3

Nếu ai đó truy cập cơ sở dữ liệu của bạn bằng mật khẩu, họ sẽ không biết mật khẩu thực. Nếu bạn triển khai hệ thống này, họ có thể tạo liên kết đặt lại và đặt lại mật khẩu. Với chuỗi ngẫu nhiên và kiến ​​thức về thỏa hiệp, bạn có thể vô hiệu hóa tất cả các chuỗi ngẫu nhiên và chỉ người dùng trong quá trình đặt lại mật khẩu mới bị xâm phạm ngay cả khi không biết về quyền truy cập. Không phải là một kịch bản có khả năng, nhưng nó có thể là giá trị xem xét cho các chi phí trên danh nghĩa của chuỗi ngẫu nhiên.

+0

Khi trang web của bạn bị xâm nhập, bạn cũng muốn đặt lại tất cả mật khẩu, vì kẻ tấn công có thể đã ghi lại chúng trong văn bản thô khi chúng được gửi tới máy chủ (trường hợp không thể tránh được; chỉ có chứng chỉ ứng dụng khách SSL mới có thể dừng). Chưa kể, kẻ tấn công có thể đã phá vỡ 90% mật khẩu băm tốt trong vòng vài giờ. Ngoài ra, nếu bạn sử dụng lời khuyên của Alex Martelli, bạn có thể thêm một kiểm tra bổ sung về yêu cầu đặt lại so với thời điểm thỏa hiệp, có hiệu quả giống như những gì bạn vừa đề xuất :) –

+0

Ngoại trừ không phải mọi người dùng đều có chuỗi ngẫu nhiên nhưng mỗi người dùng có một chuỗi được tạo ra một cách hiệu quả, vì vậy nếu bạn không ngay lập tức nhận thức được sự thỏa hiệp thì chỉ một vài người dùng bị ảnh hưởng. Bên cạnh đó 90% với mật khẩu yếu, tất nhiên. – drawnonward

+0

Gah! Đó chắc chắn là một lỗ hổng thực, mặc dù Longpoke nói, một khi kẻ tấn công nhận được trong DB tất cả các cược đã tắt: họ không cần phải liên quan đến việc đặt lại liên kết, họ chỉ có thể thay đổi mật khẩu trực tiếp trong bảng người dùng. 1 cho việc tìm kiếm nó mặc dù! – jpatokal

2

Thực tế sau khi nghĩ về điều này một lần nữa, phương pháp của bạn có khả năng an toàn hơn hơn "Luồng bình thường".

Nếu bạn chỉ cần gửi lại HASH(HASH(user's original password)), tôi có thể thấy kịch bản mà điều này có thể đưa ra một đòn bẩy kẻ tấn công:

Kịch bản 1:

  1. Jim đăng ký trên trang web của bạn như [email protected].
  2. Jim yêu cầu đặt lại mật khẩu nhưng không sử dụng. Email đặt lại được để lại trong hộp thư đến của anh ấy vĩnh cửu.
  3. Jim thay đổi địa chỉ email của anh ấy trên trang web của bạn.
  4. [email protected] bị xâm phạm bởi Bob.
  5. Bob hiện đang chạy một cuộc tấn công bruteforce qua trang trại GPGPU được phân phối của mình và khôi phục mật khẩu của Jim.

Kịch bản 2:

  1. Jim sử dụng một mật khẩu cho tài khoản ngân hàng jimjonesupinthisma! mình.
  2. Jim sổ đăng ký trên trang web của bạn là [email protected]. [email protected]không phải theo bất kỳ cách nào được liên kết với tài khoản ngân hàng của Jim.
  3. [email protected] bị xâm phạm bởi Bob.
  4. Bob hiện yêu cầu đặt lại, bây giờ anh ấy có HASH(HASH(jim's password)).
  5. Bob hiện đang chạy một cuộc tấn công bruteforce qua trang trại GPGPU được phân phối của mình và khôi phục mật khẩu của Jim mà sau đó anh ấy sử dụng để truy cập vào tài khoản ngân hàng của Jim.

Kịch bản 3:

(trang web của bạn sử dụng TLS, người dùng đăng ký qua TLS.)

  1. Jim đăng ký trên trang web của bạn như [email protected].
  2. Bob yêu cầu đặt lại mật khẩu trên tài khoản Jim s.
  3. Bob hoạt động cho NSA theo số Room 641A.
  4. Bob sử dụng trình thám thính Internet toàn cầu của mình và nhận được HASH(HASH(jim's password)) vì email được gửi bằng văn bản thuần tới [email protected].
  5. Bob hiện đang chạy một cuộc tấn công bruteforce qua trang trại GPGPU được phân phối của mình và khôi phục mật khẩu của Jim.

Biến thể của trường hợp 1 và 2 xảy ra mọi lúc (tùy thuộc vào độ mạnh của băm và mật khẩu), tôi không chắc chắn về điều đó. tận dụng kẻ tấn công chống lại người dùng của bạn.

Tôi khuyên bạn nên sử dụng mã thông báo được tạo ngẫu nhiên có không có gì để thực hiện với mật khẩu của người dùng.

+0

Xin lỗi, tôi sẽ không đồng ý ở đây: tất cả các kịch bản của bạn dường như giả định rằng chuỗi hai lần được sử dụng để khôi phục chuỗi gốc, nhưng điều này dường như không đúng. MD5 được biết là dễ bị tấn công va chạm, nhưng hacker giả định của bạn sẽ cần một cuộc tấn công preimage thành công để lấy lại mật khẩu từ băm. Cuộc tấn công tốt nhất như vậy được biết đến với một vòng MD5 chưa được pha trộn có độ phức tạp là 2^123, và việc bẻ khóa thậm chí còn chắc chắn trong lĩnh vực khoa học viễn tưởng. – jpatokal

+0

Bạn không cần (và thường không muốn) một va chạm, chỉ cần một mật khẩu (thông qua từ điển và sau đó dự phòng để bruteforce của một bảng mã thông qua 1-n chữ số). Hầu hết người dùng có mật khẩu yếu và không có băm nào thực sự cứu họ. Các cuộc tấn công này là _real_, mặc dù không phổ biến như tấn công kiddie script điển hình mà bạn nghe thấy. Trên thực tế nó là nhiều hơn để làm với quyết tâm và được ở đúng nơi vào đúng thời điểm. –

+0

Các cuộc tấn công này là thực sự chống lại MD5 chưa được cập nhật, nơi bạn có thể sử dụng một bảng cầu vồng để đảo ngược băm, nhưng các mật khẩu ở đây được muối và băm đôi. – jpatokal

0

giả sử trong một trường hợp rất hiếm, hai người dùng của bạn có cùng mật khẩu băm ngay cả sau khi kết hợp muối ngẫu nhiên với nó; sẽ có vấn đề đúng không? Tôi đoán nó sẽ không gây tổn thương nếu bạn thêm email hoặc Hashid của user_id vào liên kết đặt lại mật khẩu.

0

Chỉ cần đi ngang qua vấn đề này và có một ý tưởng:

1) Ban hành một JWT (Json Web Token) với thông tin về tài khoản của người dùng.Mã thông báo hết hạn, nói 1 giờ.

2) Gửi token cho người dùng trong một email/link

3) Người dùng nhấp vào liên kết, các dấu hiệu được gửi đến thiết bị đầu cuối máy chủ, các dấu hiệu được xác nhận. Nếu hợp lệ, bạn giải nén mã thông báo và cập nhật tài khoản người dùng

Bất kỳ sai sót nào trong phương pháp này? Không có cơ sở dữ liệu nào được chạm (ngoại trừ mật khẩu người dùng mới nếu cần)

+0

Có, bạn có thể sử dụng mã thông báo nhiều lần, nhưng tôi đồng ý với điều đó. Đó là một điều tốt. Tôi đặt hết hạn mã thông báo thành 1 giờ, vì vậy việc lạm dụng rất khó xảy ra. Tôi đang thiếu gì? Nó rất đơn giản và hoạt động rất đẹp, tôi phải bỏ lỡ một thứ gì đó. – Spock

+0

Ngoài ra, tôi sẽ đặt địa chỉ ip của yêu cầu vào mã thông báo. Sau đó, khi xác thực, khớp với ip của người gọi. Mã thông báo sau đó chỉ có thể được sử dụng từ cùng thiết bị đã bắt đầu yêu cầu. Đây chỉ là biện pháp bổ sung. IP spoofers vẫn cần mã thông báo và trong vòng 1 giờ. – Spock

Các vấn đề liên quan