2013-06-17 21 views
14

Sử dụng phản chiếu để chà một String có sử dụng String an toàn khi sử dụng char[] cho mật khẩu không? Từ khía cạnh bảo mật, thường được coi là thực tiễn tốt nhất để sử dụng char[] để lưu trữ/chuyển mật khẩu, vì người ta có thể xóa nội dung của nó sớm nhất có thể trong mã, điều này có thể đáng kể trước khi thu gom rác dọn dẹp và bộ nhớ được tái sử dụng (xóa tất cả dấu vết), giới hạn thời gian để tấn công bộ nhớ.Sử dụng an toàn String cho mật khẩu bằng cách sử dụng phản chiếu để lọc nội dung trước khi thu gom rác

Tuy nhiên, char[] là không thuận tiện như String, vì vậy nó sẽ có ích nếu người ta có thể "chà" một String nếu cần thiết, do đó làm cho String an toàn như char[].

Dưới đây là phương pháp sử dụng sự phản chiếu để không ra các trường của String.

Phương pháp này là "OK" và có đạt được mục tiêu làm cho String an toàn như char[] cho mật khẩu không?

public static void scrub(String str) throws NoSuchFieldException, IllegalAccessException { 
    Field valueField = String.class.getDeclaredField("value"); 
    Field offsetField = String.class.getDeclaredField("offset"); 
    Field countField = String.class.getDeclaredField("count"); 
    Field hashField = String.class.getDeclaredField("hash"); 
    valueField.setAccessible(true); 
    offsetField.setAccessible(true); 
    countField.setAccessible(true); 
    hashField.setAccessible(true); 
    char[] value = (char[]) valueField.get(str); 
    // overwrite the relevant array contents with null chars 
    Arrays.fill(value, offsetField.getInt(str), countField.getInt(str), '\0'); 
    countField.set(str, 0); // scrub password length too 
    hashField.set(str, 0); // the hash could be used to crack a password 
    valueField.setAccessible(false); 
    offsetField.setAccessible(false); 
    countField.setAccessible(false); 
    hashField.setAccessible(false); 
} 

Dưới đây là một thử nghiệm đơn giản:

String str = "password"; 
scrub(str); 
System.out.println('"' + str + '"'); 

Output:

"" 

Lưu ý: Bạn có thể giả định rằng mật khẩu là không String hằng số và do đó gọi phương pháp này sẽ không có tác dụng phụ có hiệu lực trên các chuỗi nội bộ.

Ngoài ra, tôi đã rời phương pháp này là trạng thái "thô" khá đơn giản vì mục đích đơn giản. Nếu tôi sử dụng nó, tôi sẽ không khai báo các ngoại lệ được ném (try/catch/bỏ qua chúng) và mã lặp lại cấu trúc lại.

+0

Vâng, dường như không tìm ra các ký tự, nhưng không phải là hoàn toàn phụ thuộc vào việc thực hiện JVM? – fge

+0

snooping bộ nhớ? đó là một cuộc tấn công tưởng tượng. tại sao không phải lo lắng về một cái gì đó thực tế hơn, như NSA snooping lưu lượng truy cập mạng của bạn. – ZhongYu

+0

Screams "hành vi không xác định" tại tôi. Chúc may mắn với rồng, velociraptors và lỗ đen :) – CodesInChaos

Trả lời

7

Có hai vấn đề an toàn tiềm năng:

  1. Các chuỗi có thể chia sẻ mảng sự ủng hộ của mình với Strings khác; ví dụ. nếu số String được tạo bằng cách gọi số substring trên số lớn hơn String. Vì vậy, khi bạn không, toàn bộ mảng value bạn có thể sẽ ghi đè trạng thái của các chuỗi khác ... không chứa mật khẩu.

    Cách khắc phục chỉ bằng 0 phần của mảng sao lưu được chuỗi mật khẩu sử dụng.

  2. JLS (17.5.3) cảnh báo rằng ảnh hưởng của việc sử dụng phản chiếu để thay đổi các biến số final là không xác định.

    Tuy nhiên, ngữ cảnh cho điều này là Mô hình bộ nhớ Java và thực tế là trình biên dịch được phép tích cực lưu vào bộ nhớ cache biến số final.Trong trường hợp này:

    • bạn mong chờ String được thread-giới hạn, và

    • bạn không nên sử dụng bất kỳ của những biến một lần nữa.

Tôi sẽ không mong đợi một trong những là thực vấn đề ... modulo sửa zeroing quá hung hăng của value.


Nhưng mối quan tâm thực sự là Velociraptors. :-)


Tôi rất bối rối khi bạn thực sự muốn ghi nhớ mật khẩu như thế này. Khi bạn nghĩ về nó, những gì bạn đang bảo vệ chống lại là khả năng ai đó có thể đọc bộ nhớ quá trình ... hoặc một dump cốt lõi hoặc tập tin trao đổi ... để lấy mật khẩu. Nhưng nếu ai đó có thể làm điều đó, bảo mật hệ thống của bạn phải đã bị xâm phạm ... cos 'những thứ đó rất có thể yêu cầu truy cập root (hoặc tương đương). Và nếu họ có quyền truy cập root, họ có thể "gỡ lỗi" chương trình của bạn và nắm bắt mật khẩu trước khi ứng dụng của bạn nén chúng.

+0

Có lẽ mã quá tàn bạo/đơn giản. Điều gì sẽ xảy ra nếu chỉ phần của mảng được trỏ đến đã bị xóa? Và chỉ số đếm được đặt bằng không (để xóa dấu vết của mật khẩu trong bao lâu)? – Bohemian

+0

Mối quan tâm lớn, an ninh, không bị ảnh hưởng bởi mối quan tâm này. Một chuỗi có thể được quan sát như bị hỏng sau khi đặt lại. –

+0

OK - Tôi đã chỉnh sửa mã để chỉ chà phần của mảng thực sự đang được sử dụng. – Bohemian

1

Một đối số mà tôi chống lại Chuỗi là quá dễ dàng để vô tình tạo một bản sao. Sử dụng dây an toàn là có thể trong lý thuyết, nhưng toàn bộ hệ sinh thái thư viện được dựa trên giả định rằng nó hoàn toàn OK để sao chép chuỗi. Cuối cùng, xem xét tất cả các hạn chế, các chuỗi có thể không thuận tiện cho trường hợp sử dụng này như thường lệ.

+0

Nhưng người ta cũng có thể sao chép 'char []'. Mặc dù điểm của bạn là hợp lệ, việc xử lý mã hóa xung quanh mật khẩu phải được xem xét chặt chẽ để đảm bảo các bản sao không được thực hiện, bất kể loại nào. – Bohemian

+1

Điểm về mất mát tiện lợi có thể giữ. –