2009-03-14 38 views
6

Các ứng dụng dựa trên web của chúng tôi có tài khoản người dùng gắn liền với người dùng có mật khẩu được chỉ định trong quá trình tạo tài khoản. Trong trường hợp của Java, làm thế nào để xử lý mật khẩu một cách an toàn, trước khi kiên trì băm của nó trong cơ sở dữ liệu.Làm thế nào để lưu trữ mật khẩu một cách an toàn trong bộ nhớ, khi tạo tài khoản?

Để cụ thể hơn, làm cách nào để đảm bảo rằng chuỗi giữ mật khẩu là rác được thu thập trong một khoảng thời gian đủ ngắn?

+0

Điều này có thể giúp bảo mật mật khẩu trong quá trình đăng ký.http: //wheelersoftware.com/articles/spring-security-hash-salt-passwords.html –

Trả lời

6

Nếu bạn có khả năng (có thể gặp khó khăn trong các ứng dụng web), sẽ tốt hơn nếu lưu trữ mật khẩu trong mảng ký tự hơn để lưu trữ chúng trong chuỗi. Nếu bạn đã hoàn thành việc lưu trữ mật khẩu, bạn có thể ghi đè lên nó trong bộ nhớ bằng cách sử dụng Array.fill() và làm tài liệu tham khảo dành cho các nhà sưu tập rác bằng cách loại bỏ nó:

Arrays.fill(password, ' '); 
password = null; 

Tôi chỉ nhận thấy rằng nulling mật khẩu sẽ là một chút hoang tưởng nhưng bạn có thể làm gì nếu nó cam đoan với bạn :)

+0

Nếu điều này là có thể trong một ứng dụng web - hãy đọc mật khẩu từ dòng đầu vào servlet vào một mảng byte, và sau đó điền vào mảng với số không sau khi lưu trữ mật khẩu, sau đó nó sẽ trở thành một cách tiếp cận khả thi. Dự án Java OWASP sử dụng nó trong một ví dụ, nhưng không sử dụng cho các mật khẩu bền bỉ. –

+2

Điều này không yêu cầu bộ thu gom rác không nén ngăn xếp và do đó để lại một bản sao của mảng ở nơi khác trong bộ nhớ? –

+1

@KeeperOfTheSoul: Vâng, cuối cùng nó phụ thuộc vào hành vi của GC. Nó cũng phụ thuộc vào việc mảng sẽ được serialized hay không. Tất cả trong tất cả, tôi ước rằng Java có một lớp SecureString tương tự như trong Microsoft .Net. –

4

Nếu bạn tạo băm ở phía máy khách, không cần phải suy nghĩ về vấn đề này. Mật khẩu đơn giản không bao giờ được gửi đến máy chủ.

+0

Vâng, đó là một cách tiếp cận tốt, nhưng sau đó không phải điều đó cũng để lại những kẻ tấn công có khả năng nghiên cứu thuật toán băm được sử dụng? Cấp rằng nó là an ninh thông qua tối tăm theo một cách, nhưng nó không giới hạn số lượng thông tin có sẵn cho kẻ tấn công về cách mật khẩu được lưu trữ. –

+0

Đó sẽ là một lựa chọn nhưng không thể kẻ tấn công đánh chặn băm do khách hàng tạo ra, và sau đó chỉ cần tạo lại cùng một yêu cầu HTTP để đăng nhập? –

+0

@Markus, HTTPS luôn được sử dụng, do đó xác suất của cuộc tấn công MITM là thấp hoặc nill. –

2

Hai từ: Phạm vi cục bộ. Các biến được khai báo để xử lý mật khẩu cần phải có phạm vi nhỏ nhất tuyệt đối có thể.

Khi các biến nằm ngoài phạm vi, các đối tượng đủ điều kiện để thu thập rác.

Thông thường, bạn đang chọn mọi thứ theo yêu cầu. Bạn muốn có một giao dịch rất nhỏ, chấp nhận yêu cầu, băm mật khẩu, duy trì nó và chuyển hướng. Trang mà bạn chuyển hướng sau đó có thể tìm nạp nội dung và thực hiện tất cả quá trình xử lý "khác" là một phần của ứng dụng của bạn.

1

Không có cách nào để đảm bảo rằng mật khẩu văn bản rõ ràng bị xóa khỏi bộ nhớ trong Java.

Tuy nhiên, tin tặc không cần quyền truy cập vào bộ nhớ của chương trình để nhận mật khẩu văn bản rõ ràng. Có nhiều cách đơn giản hơn (chẳng hạn như đánh hơi các gói dữ liệu) nên rất khó có ai dựa vào phương pháp này.

Cách tiếp cận tốt nhất là yêu cầu khách hàng mã hóa mật khẩu như @ Mork0075 đề xuất. Tuy nhiên, trong khi nó có nghĩa là bạn không thể dễ dàng nhận được mật khẩu, một chương trình vẫn có thể nhận được phiên bản mã hóa của mật khẩu và do đó giả vờ là một người sử dụng. Một cách xung quanh việc này là mã hóa toàn bộ kết nối bằng SSL.

Tất cả điều này là khá học thuật, vì cách tiếp cận đơn giản nhất cho một hacker là theo dõi các gói dữ liệu đến cơ sở dữ liệu và lấy mật khẩu cho cơ sở dữ liệu của bạn. Tôi nghi ngờ truy cập trực tiếp vào cơ sở dữ liệu của bạn có liên quan nhiều hơn ... hoặc có lẽ nó không phải là. ;)

+0

Tôi đang xem xét việc bảo vệ mật khẩu, không phải vì kẻ tấn công sẽ thử phương pháp này - hộp đã bị xâm phạm nếu anh ta có thể nhìn trộm vào bộ nhớ, vì vậy có những điều lớn hơn phải lo lắng. Tôi đang tìm cách ngăn chặn mật khẩu xuất hiện trong một bãi chứa đống Java thu được để chẩn đoán. –

0

Sử dụng một thách thức mật khẩu:

  1. server chọn một giá trị thách thức và gửi nó đến các khách hàng
  2. Máy chủ thực hiện dịch 1 chiều với mật khẩu và thử thách, ví dụ. MD5(CONCAT(challenge, password)) và gán nó cho phiên.
  3. Mật khẩu văn bản thuần túy hiện đã nằm ngoài phạm vi và sẵn sàng thu gom rác.
  4. Khách hàng cũng thực hiện cùng một bản dịch và gửi kết quả đến Máy chủ.
  5. Nếu Máy chủ và Máy khách chọn cùng giá trị cuối cùng, ứng dụng khách sẽ được xác thực.

Phương pháp này ngăn chặn các cuộc tấn công replay , nhưng đòi hỏi sự thách thức giá trị là rất khó lường (ngẫu nhiên) và không thường xuyên tái sử dụng (dài).

Mật khẩu thuần văn bản chỉ nằm trong phạm vi xử lý yêu cầu kết nối ban đầu - không phải trong quá trình xác thực. Nó không quan trọng bao lâu kết quả dịch thuật 1 chiều nằm trong phạm vi (không thu thập rác) vì nó có giá trị phát lại ít.

+0

Điều đó sẽ làm việc tốt cho quá trình đăng nhập nhưng tác giả yêu cầu đăng ký tài khoản, vì vậy bạn phải lưu trữ giá trị băm trong cơ sở dữ liệu. Hàm băm này không thể được tạo thông qua một giá trị thử thách vì nó không thể được khôi phục khi đăng nhập. –

5

Bạn không sử dụng chuỗi. Bạn sử dụng một char [] và sau đó ghi đè lên char [] khi hoàn thành.

Hoàn toàn không có sự đảm bảo nào khi nói đến thu gom rác thải (ngoài việc bộ hoàn thiện sẽ chạy trước khi đối tượng được thu thập). GC có thể không bao giờ chạy, nếu nó chạy nó có thể không bao giờ GC chuỗi có mật khẩu trong đó.

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