it-swarm-vi.com

Làm thế nào để thực hiện an toàn tính năng "Ghi nhớ tôi"?

Giả sử bạn đã có một trang web thực hiện tất cả các công cụ đăng nhập tiêu chuẩn, cách chính xác và an toàn nhất để cho phép người dùng tự động đăng nhập trong một khoảng thời gian nhất định (giả sử 30 ngày)? Khoảng thời gian này cần được thực thi nghiêm ngặt; tức là, tôi không nghĩ rằng một giải pháp hợp lệ sẽ cho cookie một ngày hết hạn và hy vọng trình duyệt của người dùng sẽ xóa nó kịp thời.

Chi tiết về hệ thống đăng nhập hiện có:

  • Người dùng phải nhập tên người dùng và mật khẩu
  • Cơ sở dữ liệu lưu trữ tên người dùng cũng như strong_hash_feft (mật khẩu + user_specific_random_salt)
  • Các biểu mẫu đăng nhập được tải và gửi qua SSL, như tất cả các trang tiếp theo

Có rất nhiều ví dụ ngoài kia và nhiều ví dụ có lỗi bảo mật rõ ràng. Hãy sử dụng PHP làm ngôn ngữ đích nhưng các khái niệm nên được áp dụng cho bất kỳ ngôn ngữ nào.

57
colithium

Câu trả lời của tôi không đầy đủ và có một lỗ hổng không cần thiết, trong một số trường hợp - vui lòng xem câu trả lời của @ Scott thay vào đó.


Có hai phần cho câu trả lời của tôi:

Đầu tiên, giả sử mô hình mối đe dọa của bạn không lo lắng về việc tiếp xúc với cookie của khách hàng , bạn có thể tạo và lưu trữ một nonce ở phía máy chủ, băm nó với tên người dùng và thông tin khác (ví dụ: ip máy khách, tên máy tính, dấu thời gian, nội dung tương tự) và gửi nó trong cookie. Nonce nên được lưu trữ trong cơ sở dữ liệu, cùng với ngày hết hạn và cả hai đều được kiểm tra khi cookie quay trở lại.
[.___.] Đây chỉ là cookie "ghi nhớ", KHÔNG phải là cookie phiên - tức là khi bạn nhận được cookie đó mà không có phiên, hãy phát hành lại cookie phiên mới, thông thường. Cũng lưu ý rằng giống như cookie phiên, điều này chỉ được phân phối qua https và sử dụng các thuộc tính securehttpOnly, và tất nhiên là có phạm vi cookie đúng, v.v.

Thứ hai, đối với người dùng đã được ghi nhớ, bạn nên (có thể, tùy thuộc vào độ nhạy) gọi quy trình xác nhận lại cho các hoạt động nhạy cảm nhất định. Đó là, đôi khi họ sẽ cần phải đặt lại mật khẩu của mình, nhưng hiếm khi, và chỉ cho các hoạt động nhạy cảm. Điều này là để ngăn chặn các cuộc tấn công như CSRF và chia sẻ phơi nhiễm trên máy tính để bàn.

31
AviD

Tôi đã viết rất dài về đăng nhập an toàn và hộp kiểm "nhớ tôi" . Câu trả lời được chấp nhận không sai, nhưng tôi cho rằng nó phức tạp hơn một chút so với yêu cầu và bỏ qua một lĩnh vực cần sự phức tạp hơn một chút.

tạo và lưu trữ một nonce ở phía máy chủ, băm với tên người dùng và thông tin khác (ví dụ: ip máy khách, tên máy tính, dấu thời gian, nội dung tương tự) và gửi nó trong cookie. Nonce nên được lưu trữ trong cơ sở dữ liệu, cùng với ngày hết hạn và cả hai đều được kiểm tra khi cookie quay trở lại.

Vì vậy, việc triển khai không tiết lộ bất kỳ thông tin nào cho khách hàng có thể trông giống như ...

// Storage:
setcookie(
    'rememberme',
    hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce),
    time() + 8640000 // 100 days, for example
);
// Validation:
$valid = hash_equals(
    $_COOKIE['rememberme'],
    hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce)
);

Hạn chế rõ ràng ở đây là, nếu địa chỉ IP của bạn (hoặc thông tin khác) thay đổi, cookie của bạn là vô dụng. Một số người có thể coi đây là một điều tốt, tôi thấy nó là sự thù địch không cần thiết đối với khả năng sử dụng đối với người dùng Tor.

Bạn chắc chắn có thể giải thích trích dẫn ở trên có nghĩa là một cái gì đó khác nhau, như mã thông báo Web JSON của một người nghèo, quá. Tuy nhiên, cookie HTTP được giới hạn ở 4 KiB mỗi tên miền. Không gian ở mức cao.

Một vấn đề khác: Có bao nhiêu thông tin truy vấn cơ sở dữ liệu của bạn rò rỉ về ứng dụng của bạn? (Vâng, tôi đang nói về các kênh bên.)


Chiến lược "Ghi nhớ" an toàn của Paragon Initiative

Lưu trữ:

  1. Tạo một chuỗi 9 byte ngẫu nhiên từ random_bytes() (PHP 7.0+ hoặc thông qua Random_compat ), base64 mã hóa nó thành 12. Điều này sẽ được sử dụng để tra cứu cơ sở dữ liệu.
  2. Tạo một chuỗi ngẫu nhiên khác, tốt nhất là dài ít nhất 18 byte và một lần nữa base64 mã hóa nó (thành 24+). Điều này thực sự sẽ được sử dụng để xác thực.
  3. Lưu trữ $lookuphash('sha256, $validator) trong cơ sở dữ liệu; tất nhiên liên quan đến một tài khoản người dùng cụ thể.
  4. Lưu trữ $lookup . $validator Trong cookie HTTP của người dùng (ví dụ: rememberme).

Xác thực (Đăng nhập tự động):

  1. Chia cookie thành $lookup$validator.
  2. Thực hiện tra cứu cơ sở dữ liệu dựa trên $lookup; Không sao nếu có kênh bên thời gian ở đây.
  3. Kiểm tra hash_equals($row['hashedValdator'], hash('sha256', $validator)).
  4. Nếu bước 3 trả về TRUE, hãy liên kết phiên hiện tại với tài khoản người dùng phù hợp.

Phân tích bảo mật:

  • Kênh phụ nào được giảm nhẹ?
    [.___.] Đáng kể nhất: nó giảm thiểu tác động của rò rỉ thông tin thời gian đối với hoạt động so sánh chuỗi được sử dụng trong tra cứu cơ sở dữ liệu.

    Nếu bạn đã triển khai xác thực mã thông báo ngẫu nhiên ngây thơ, kẻ tấn công có thể gửi rất nhiều yêu cầu cho đến khi họ tìm thấy mã xác thực hợp lệ cho người dùng. (Có lẽ họ sẽ không thể chọn nạn nhân mà họ đang mạo danh.)

  • Điều gì xảy ra nếu kẻ tấn công có thể rò rỉ bảng cơ sở dữ liệu xác thực dài hạn?
    [.__.] Chúng tôi đã lưu trữ hàm băm SHA256 của $validator Trong cơ sở dữ liệu, nhưng bản rõ cho hàm băm được lưu trữ trong cookie. Vì đầu vào là một giá trị entropy cao, nên brute-force tìm kiếm điều này không có khả năng mang lại bất kỳ kết quả nào. (Điều này cũng giảm thiểu sự cần thiết của ví dụ: bcrypt.)

Chiến lược này được thực hiện trong Gatekeeper .

10
Scott Arciszewski

Đó là một câu hỏi thú vị. Tôi sẽ bắt đầu bằng cách nói rằng tôi không chắc nó có thể được thực hiện mà không làm suy yếu tính bảo mật của ứng dụng, nhưng sau đó tùy thuộc vào trang web có thể được coi là đáng để đánh đổi.

Vì vậy, một cách tiếp cận có thể là

Cơ sở dữ liệu trạng thái phiên sẽ cần ghi lại thời gian mã thông báo được đặt và thời lượng cần ghi nhớ để có thể so sánh mã thông báo được trình bày.

Khi người dùng đăng nhập vào ứng dụng, họ có một hộp kiểm cho phép họ đăng nhập (lý tưởng với một khoảng thời gian để người dùng chọn)

Khi mã thông báo phiên được đặt, khoảng thời gian đó được sử dụng làm hết hạn cookie. Trong các lần truy cập tiếp theo, cookie sẽ được hiển thị cho ứng dụng và máy chủ sẽ cần kiểm tra xem nó có còn hiệu lực hay không (tức là thời hạn sử dụng cho chức năng ghi nhớ tôi đã không bị tấn công). Nếu mã thông báo vẫn còn hiệu lực, người dùng được coi là xác thực, nếu không thì mã thông báo sẽ bị xóa và người dùng được chuyển hướng đến màn hình đăng nhập.

Vấn đề với phương pháp này. Các trình duyệt được chia sẻ có nghĩa là có thể truy cập trái phép.

Ngoài ra, bất kỳ ai có thể truy cập cookie (thông qua lỗ hổng trong trang web, sự cố trình duyệt hoặc thông qua phần mềm độc hại được cài đặt trên máy) đều có thể truy cập trái phép vào trang web. Một đề xuất chung để giảm thiểu điều này là cố gắng gắn cookie vào địa chỉ IP nguồn (tất nhiên được mã hóa hoặc lưu trữ trên máy chủ), được kiểm tra khi người dùng trình bày cookie, tuy nhiên điều này gây ra sự cố với môi trường công ty lớn nơi người dùng có thể đến từ một số địa chỉ IP và cũng có thể dễ bị giả mạo.

5
Rory McCune

Bạn không phải phụ thuộc vào trình duyệt để xóa cookie, bạn có trang web kiểm tra ngày hết hạn trên cookie.

Trên thực tế, để đảm bảo an toàn, tôi muốn nói rằng đó có lẽ là điều bạn sẽ phải làm, vì bạn muốn đặt ngày hết hạn là một phần của giá trị cookie và mã hóa nó thay vì dựa vào thuộc tính hết hạn văn bản đơn giản của cookie.

Và bạn thực sự muốn đánh dấu cookie là an toàn và sử dụng cookie thứ cấp trong suốt thời gian của một phiên riêng lẻ hoặc bảo vệ toàn bộ phiên (không chỉ quá trình đăng nhập) bằng SSL để ngăn chặn cookie bị đánh cắp khỏi dây và được sử dụng bởi một bên trái phép.

4
Xander

Bài viết này mô tả cách tiếp cận chống trộm cắp cookie và đoán ID phiên:

  • Cookie "nhớ tôi" bao gồm ID người dùng, mã thông báo (số ngẫu nhiên lớn) và mã thông báo chuỗi (một số ngẫu nhiên lớn khác).
  • Khi người dùng trình bày cookie, cơ sở dữ liệu được tìm kiếm cho ba mẩu thông tin này. [.__.]
    • Nếu được tìm thấy, mã thông báo chuỗi được tạo lại, được lưu trữ trong cơ sở dữ liệu và được gửi đến người dùng
    • Nếu chỉ tìm thấy tên người dùng và mã thông báo, có thể người khác đã đánh cắp cookie vì mã thông báo chuỗi đã được sử dụng. Sau đó, hệ thống có thể cảnh báo người dùng và/hoặc xóa tất cả các mã thông báo được lưu trữ khỏi người dùng này khỏi cơ sở dữ liệu.

Là một biện pháp bảo mật bổ sung, chúng tôi khuyên rằng các hành động quan trọng như thay đổi dữ liệu đăng nhập hoặc thanh toán mọi thứ yêu cầu mật khẩu, nếu người dùng chỉ được xác thực bằng cookie "nhớ tôi".

Bảng cơ sở dữ liệu chứa id người dùng và mã thông báo cũng chứa ngày hết hạn của mã thông báo. Nó cũng có thể chứa tác nhân người dùng và địa chỉ IP để kẻ tấn công cũng phải sao chép chúng. Tất cả các mã thông báo chỉ nên được lưu trữ dưới dạng băm vì về cơ bản chúng hoạt động giống như mật khẩu và sẽ cho phép kẻ tấn công, người có được cơ sở dữ liệu, đăng nhập.

Tôi đã tạo một triển khai mẫ cho PHP.

0
chiborg