Các giải pháp thay thế để gửi mật khẩu văn bản rõ khi đăng nhập

Jan 02 2021

Lưu ý: Tôi đã đọc Có thể gửi mật khẩu văn bản thuần túy qua HTTPS không? và bảo mật https - mật khẩu nên được băm phía máy chủ hay phía máy khách? , nhưng ở đây là về một phương pháp thay thế cụ thể (xem bên dưới).


Sau khi đọc một bài viết về phương pháp xác thực mới trên blog Cloudflare , tôi đã xem xét các POSTyêu cầu được gửi trong khi xác thực bằng "Công cụ dành cho nhà phát triển> Mạng". Nhiều trang web phổ biến (Reddit, HN, v.v.) vẫn gửi mật khẩu ở dạng văn bản rõ trong POSTyêu cầu ( bảo mật SSL) (xem ảnh chụp màn hình bên dưới).

Phương thức đăng nhập này có còn là tiêu chuẩn của ngành không?

Giải pháp thay thế sau có an toàn hơn gửi mật khẩu văn bản rõ qua HTTPS không?

  • đăng ký: khách hàng tạo ngẫu nhiên saltvà gửi tuple (username, salt, hash(plain_password + salt))thông qua một POSTyêu cầu. Sau đó, mật khẩu văn bản rõ ràng sẽ không bao giờ đến được máy chủ.

  • các lần đăng nhập tiếp theo: máy chủ phải gửi saltlại cho bất kỳ máy khách nào cố gắng đăng nhập bằng một mã đã cho username, để máy khách có thể băm với cùng một muối. Vì vậy, điều này có nghĩa là máy chủ đang tiết lộ saltcho bất kỳ ai cố gắng đăng nhập bằng tên người dùng nhất định.

  • lợi ích: máy chủ lưu trữ mật khẩu muối + băm (là tiêu chuẩn) nhưng máy chủ cũng chưa từng thấy mật khẩu văn bản rõ dù chỉ một lần (vì vậy nếu máy chủ bị xâm phạm, rủi ro sẽ được hạn chế)

Ghi chú:

  • H = hash(plain_password + salt)bây giờ hoạt động giống như một cái mới plaintext(xem câu trả lời thứ 2 của Zero Knowledge Password Proof: tại sao băm mật khẩu ở phía máy khách không phải là ZKP? ), thì máy chủ có thể lưu trữ (username, salt, server_salt, hash(H + server_salt))trong cơ sở dữ liệu, thay vì (username, salt, H).

  • để giảm thiểu rủi ro cho các cuộc tấn công phát lại, máy chủ cũng có thể gửi một mã duy nhất nonce, cùng với saltmỗi lần đăng nhập, sẽ hết hạn sau một lần đăng nhập

  • mục tiêu chính ở đây là máy chủ không bao giờ có quyền truy cập vào mật khẩu văn bản rõ ràng hoặc một hàm băm đơn giản của nó (thường có thể được đảo ngược với một bảng cầu vồng duy nhất cho toàn bộ trang web). Tôi đồng ý với rủi ro rằng kẻ tấn công phải tính toán một bảng cầu vồng cho mỗi người dùng .

  • Ví dụ về cuộc tấn công mà tôi muốn giảm thiểu: nếu máy chủ có quyền truy cập vào mật khẩu văn bản rõ và nó bị xâm phạm (ví dụ: Spectre / Meltdown vuln.) Thì mật khẩu văn bản rõ của người dùng (có thể được sử dụng lại trên các trang web khác) có thể bị đánh cắp, trước khi nó bị muối - băm và lưu vào cơ sở dữ liệu.


Trả lời

14 SteffenUllrich Jan 02 2021 at 14:38

Tôi không thấy đề xuất của bạn tốt hơn cách tiếp cận băm phía khách hàng hiện tại như thế nào, nhưng tôi thấy việc triển khai nó phức tạp hơn các phương pháp khác. Rất tiếc, bạn không mô tả một rủi ro cụ thể mà bạn đang cố gắng truy cập, vì vậy tôi chỉ giả sử các mối đe dọa điển hình thường thấy.

Kẻ tấn công Man in the Middle

Trong trường hợp này, giả định rằng một số người đàn ông ở giữa có quyền truy cập vào lưu lượng truy cập, chẳng hạn như vì nó đã xâm phạm một số chặn TLS lưu lượng truy cập đáng tin cậy trong tường lửa của công ty hoặc nắm giữ CA đáng tin cậy như trong trường hợp superfish .

Trong trường hợp này, kẻ tấn công có quyền truy cập Hgiống như trước đây plain_password. Vì Hlà mọi thứ cần thiết để xác thực nên kẻ tấn công đã thành công và cách tiếp cận của bạn không thêm bất kỳ biện pháp bảo vệ bổ sung nào ở đây .

Ẩn mật khẩu yếu và sử dụng lại mật khẩu

Đối số phổ biến cho phép băm phía máy khách là không để lộ mật khẩu yếu hoặc được sử dụng lại cho máy chủ, mà thay vào đó xác thực bằng một mật khẩu dẫn xuất phức tạp. Cách tiếp cận của bạn thực hiện điều này bằng cách băm plain_passwordvới một số người dùng được tạo ngẫu nhiên saltvà sau đó gửi Hsaltđến máy chủ khi thiết lập mật khẩu.

Mặc dù điều này hoạt động nhưng mọi xác thực hiện yêu cầu một bước bổ sung : đầu tiên nó cần truy xuất muối đã sử dụng trước đó cho người dùng từ người dùng và sau đó nó có thể sử dụng điều này saltđể băm plain_password. Bước bổ sung này làm cho việc xác thực trở nên phức tạp hơn vì trước tiên nó cần kiểm tra người dùng với máy chủ và sau đó nó có thể kiểm tra mật khẩu. Ngoài ra, một triển khai nhỏ của điều này sẽ mở ra một rò rỉ thông tin vì nó giúp bạn có thể kiểm tra xem người dùng có tồn tại ngay từ đầu hay không (có trả về muối hay không) mà không cần xác thực thêm.

Rò rỉ thông tin này có thể được đóng lại bằng cách máy chủ trả về một số muối bất kể người dùng có tồn tại hay không. Tất nhiên, đây không thể chỉ là một muối ngẫu nhiên vì nếu không, kẻ tấn công có thể kiểm tra hai lần cùng một người dùng và kết luận rằng người dùng đó không tồn tại nếu muối trả về khác. Vì vậy, muối thực sự phải được cố định cho người dùng không tồn tại, tức là bắt nguồn từ tên người dùng.

Và điều này cũng cho thấy một con đường để đơn giản hóa cách tiếp cận của bạn : thay vì người dùng tạo ra một muối ngẫu nhiên, lưu trữ nó ở máy chủ và truy xuất lại sau đó, người ta có thể chỉ cần lấy muối từ tên người dùng ở phía máy khách . Đơn giản salt=hash(username+domain)là đủ để tạo một muối duy nhất cho mỗi miền và do đó làm cho cả hai saltHkhác nhau ngay cả khi usernameplain_passwordđược sử dụng lại trên các miền khác nhau. Và trái với cách tiếp cận của bạn, không cần thêm chuyến đi đến máy chủ để truy xuất muối đã sử dụng trước đó cho người dùng.


Tóm lại: cách tiếp cận đơn giản này về cơ bản là gửi hash(plain_password+username+domain)thay vì mật khẩu ban đầu. Miền được thêm vào để đảm bảo rằng ngay cả khi usernameplain_passwordđược sử dụng lại trên nhiều trang web, mật khẩu bắt nguồn sẽ không được sử dụng lại.

8 mti2935 Jan 02 2021 at 21:33

Đây chính xác là vấn đề mà các giao thức như PAKE và SRP muốn giải quyết. Với PAKE / SRP, máy khách và máy chủ xác thực lẫn nhau dựa trên mật khẩu mà máy khách đã biết (và một dẫn xuất của mật khẩu mà máy chủ biết).

Máy khách chứng minh cho máy chủ biết rằng nó biết mật khẩu mà không cần máy khách gửi mật khẩu (hoặc dữ liệu tương đương mật khẩu) đến máy chủ. Vào cuối quá trình, máy khách và máy chủ chia sẻ một bí mật chung.

Máy chủ không lưu trữ mật khẩu (hoặc dữ liệu tương đương với mật khẩu) và không dễ bị tấn công từ điển. Kẻ nghe trộm hoặc kẻ trung gian có thể xem bản rõ được gửi qua đường dây không thể lấy đủ thông tin để lấy được mật khẩu. Điều này ngăn chặn hiệu quả các cuộc tấn công trung gian bằng cách sử dụng chứng chỉ giả và ngăn các trang web 'lừa đảo' lấy cắp mật khẩu của người dùng.

Để biết rõ về cách 1 mật mã triển khai SRP, hãy xem https://blog.1password.com/developers-how-we-use-srp-and-you-can-too/

5 mentallurg Jan 02 2021 at 16:00

Ngoài câu trả lời của Steffen Ullrich :

Nếu trong quá trình đăng nhập, người dùng chỉ gửi mã băm, thì kẻ tấn công không cần biết mật khẩu. Nó là đủ để đánh cắp cơ sở dữ liệu mật khẩu. Sau đó, trong khi yêu cầu đăng nhập, kẻ tấn công sẽ chỉ gửi băm từ cơ sở dữ liệu. Máy chủ sẽ không phân biệt được liệu khách hàng đã sử dụng mật khẩu và băm nó hay máy khách (kẻ tấn công) chỉ đơn giản gửi mã băm.

Bài báo về OPAQUE cũng giải quyết vấn đề này: Đánh cắp cơ sở dữ liệu mật khẩu sẽ không giúp được kẻ tấn công. Một người sẽ cần biết mật khẩu người dùng đơn giản.

3 MargaretBloom Jan 03 2021 at 08:43

Nếu kẻ tấn công xâm phạm máy chủ của bạn, chúng không chỉ kiểm soát phần mềm chạy trên máy chủ của bạn mà còn kiểm soát phần mềm chạy trên máy khách.
Bất kể bạn đã thiết kế sơ đồ xác thực được thiết kế đẹp mắt nào, kẻ tấn công có thể thay đổi nó trước khi nó được gửi đến trình duyệt.
Bây giờ bạn gặp sự cố với quả trứng gà: bạn không thể bảo mật mật khẩu nếu kẻ tấn công kiểm soát cách nó được thu thập và gửi đến máy chủ của bạn.

Nếu bạn lo lắng về việc vi phạm dữ liệu, phương pháp của bạn sẽ hoạt động như một biện pháp bảo vệ, nhưng phía máy chủ băm mật khẩu thích hợp cũng vậy.

Nếu bạn lo lắng về các cuộc tấn công MITM, TLS sẽ giải quyết chúng.
Nếu bạn lo lắng về các cuộc tấn công của MITM trên TLS, thì, như tôi muốn nói, cách phòng thủ tốt trước chúng luôn bắt đầu với sách hướng dẫn Krav Maga. Kẻ tấn công có đủ nguồn lực để phá vỡ TLS một cách nhất quán không có vấn đề gì khi lấy được thứ chúng muốn từ bất kỳ cá nhân nào không được đào tạo bài bản và đặc biệt (vâng, tôi đang nói về tra tấn, tống tiền, bắt cóc và giết người).

Nếu bạn lo lắng về một tác nhân đe dọa chỉ có thể đọc dữ liệu mà máy chủ nhận được, thì cách tiếp cận của bạn (như đã được sửa bởi Steffen) sẽ chống lại chúng. Tuy nhiên, đây là một trường hợp kỳ lạ và hiếm gặp, thường phát sinh từ một máy chủ được định cấu hình sai và các hoạt động phát triển không tốt (tức là gửi thông tin xác thực qua các yêu cầu GET và lưu trữ công khai nhật ký truy cập). Việc khắc phục những sai lầm này dễ dàng hơn là phát minh ra một giao thức chỉ để đối phó với chúng.

Lưu ý rằng cả hai lỗ hổng mà bạn đã đề cập (thực ra chỉ là một, vì Meltdown về mặt kỹ thuật là một biến thể của Spectre) cuối cùng sẽ dẫn đến leo thang đặc quyền cục bộ, cho phép kẻ tấn công toàn quyền kiểm soát máy chủ web của bạn. Một lần nữa làm nổi bật trường hợp hiếm khi kẻ tấn công có quyền truy cập chỉ đọc vào dữ liệu mà máy chủ web của bạn nhận được.

Vì vậy, lý do mà nhiều trang web lớn không sử dụng nó, đó là vì nó không bổ sung gì nhiều ngoài những trường hợp cụ thể mà rất có thể là cấu hình sai. Cũng cần lưu ý rằng nếu kẻ tấn công có thể đọc được dữ liệu nào đang chuyển đổi tại máy chủ của bạn, thì bạn đang ở phía bên thua cuộc của trò chơi. Xin lưu ý với tôi, thật tốt khi có các biện pháp bảo vệ nhiều lớp, nhưng mục tiêu chính của bạn không phải là để nó xảy ra ngay từ đầu. Và tập trung vào đó cũng sẽ giúp bạn không phải phát minh ra các kế hoạch mới.

Dù sao, như Steffen đã cho thấy, kế hoạch đề xuất của bạn có thể hoạt động trở lại một mô hình tấn công kỳ lạ như vậy. Tôi vẫn sẽ sử dụng hash(hash(domain + username) + password)thay vì hash(domain + username + password)chỉ để loại trừ khả năng từ xa domain + username + passwordvẫn là một từ trong từ điển.
Như mti2935 đã cho thấy, SRP là một sự thay thế thú vị hơn. Xác thực dựa trên chứng chỉ (tức là xác thực do trình duyệt xử lý) là một tùy chọn khác (mà tôi thấy tốt hơn là thực hiện theo cách thủ công trong một tập lệnh JS, có khả năng bị ô nhiễm, như bạn đã đề xuất trong các nhận xét).