java - violation - heap inspection vb net




為什麼char[]比字符串更適合密碼? (12)

在Swing中,密碼字段有一個getPassword() (返回char[] )方法,而不是通常的getText() (返回String )方法。 同樣,我遇到了一個不使用String來處理密碼的建議。

為什麼String在密碼方面會對安全構成威脅? 使用char[]感覺不方便。


  1. 如果你將密碼存儲為純文本,那麼字符串在Java中是不可變的 ,它將在內存中可用,直到垃圾收集器清除它,並且因為字符串池中的字符串用於可重用性,所以很有可能它會長時間保留在內存中持續時間,構成安全威脅。 由於任何有權訪問內存轉儲的人都可以以明文形式找到密碼
  2. Java推薦使用JPasswordField的getPassword()方法,它返回一個char []和不推薦使用的getText()方法,該方法以明文形式返回密碼,說明安全原因。
  3. toString()總是存在在日誌文件或控制台中打印純文本的風險,但如果使用Array,則不會打印數組的內容而是打印其內存位置。

    String strPwd = "passwd";
    char[] charPwd = new char[]{'p','a','s','s','w','d'};
    System.out.println("String password: " + strPwd );
    System.out.println("Character password: " + charPwd );
    

    字符串密碼:passwd

    字符密碼:[C @ 110b2345

最後的想法:儘管使用char []還不夠,你需要擦除內容才能更安全。 我還建議使用散列或加密密碼而不是純文本,並在驗證完成後立即從內存中清除它。


字符串是不可變的 。 這意味著一旦你創建了String ,如果另一個進程可以轉儲內存,那麼除了reflection之外你沒有辦法在垃圾收集開始之前擺脫數據。

使用數組,您可以在完成數據後顯式擦除數據。 您可以使用您喜歡的任何內容覆蓋數組,即使在垃圾回收之前,密碼也不會出現在系統的任何位置。

所以,是的,這一個安全問題 - 但即使使用char[]只會減少攻擊者的機會窗口,而且只針對這種特定類型的攻擊。

正如評論中所指出的,垃圾收集器移動的數組可能會將數據的雜散副本留在內存中。 我相信這是特定於實現的 - 垃圾收集器可以清除所有內存,以避免這種情況。 即使它確實存在,仍然有時間char[]包含實際字符作為攻擊窗口。


字符數組( char[] )可以在使用後通過將每個字符設置為零而不使用字符串來清除。 如果有人可以以某種方式查看內存映像,如果使用了字符串,他們可以以純文本形式查看密碼,但如果使用char[] ,則在使用0清除數據後,密碼是安全的。


已經給出了答案,但我想分享一下我最近在Java標準庫中發現的問題。 雖然他們現在非常小心地用char[]替換密碼字符串(當然這是一件好事),但是當從內存中清除它時,其他安全關鍵數據似乎被忽略了。

我在考慮例如PrivateKey類。 考慮一種情況,您可以從PKCS#12文件加載私有RSA密鑰,使用它來執行某些操作。 現在,在這種情況下,只要對密鑰文件的物理訪問受到適當限制,單獨嗅探密碼對您沒有多大幫助。 作為攻擊者,如果您直接獲得密鑰而不是密碼,那將會好得多。 所需的信息可以洩漏,核心轉儲,調試器會話或交換文件只是一些例子。

事實證明,沒有任何東西可以讓你從內存中清除PrivateKey的私人信息,因為沒有API可以讓你擦除形成相應信息的字節。

這是一個糟糕的情況,因為paper描述了這種情況如何可能被利用。

例如,OpenSSL庫在釋放私鑰之前覆蓋關鍵內存部分。 由於Java是垃圾收集的,我們需要顯式方法來擦除和使Java密鑰的私有信息無效,這些密鑰將在使用密鑰後立即應用。


我不認為這是一個有效的建議,但是,我至少可以猜測原因。

我認為動機是要確保您可以在使用後及時清除內存中的所有密碼。 使用char[]您可以用空格或某些東西覆蓋數組的每個元素。 您無法以這種方式編輯String的內部值。

但僅此一點並不是一個好的答案; 為什麼不確保對char[]String的引用不會被轉義? 然後沒有安全問題。 但問題是String對象可以在理論上進行內部intern()編輯並在常量池中保持活動狀態。 我想使用char[]禁止這種可能性。


有些人認為,一旦不再需要密碼,就必須覆蓋用於存儲密碼的內存。 這減少了攻擊者從系統中讀取密碼的時間窗口,並完全忽略了攻擊者已經需要足夠的訪問權來劫持JVM內存來執行此操作的事實。 具有這麼多訪問權限的攻擊者可以捕獲您的關鍵事件,使其完全無用(AFAIK,所以如果我錯了請糾正我)。

更新

感謝我的評論,我必須更新我的答案。 顯然有兩種情況可以增加(非常)次要的安全性改進,因為它減少了密碼落在硬盤上的時間。 我認為對於大多數用例來說,這樣做太過分了。

  • 您的目標系統可能配置不當,或者您必須假設它並且您必須對核心轉儲感到偏執(如果系統不由管理員管理,則可能有效)。
  • 您的軟件必須過於偏執,以防止數據洩露,攻擊者可以訪問硬件 - 使用TrueCrypt (已停產), VeraCryptCipherShed

如果可能,禁用核心轉儲和交換文件將解決這兩個問題。 但是,它們需要管理員權限並且可能會降低功能(使用的內存更少),並且從正在運行的系統中提取RAM仍然是一個有效的問題。


這些都是原因,應該選擇char []數組而不是String作為密碼。

1.由於如果你將密碼存儲為純文本字符串在Java中是不可變的,它將在內存中可用,直到垃圾收集器清除它並且因為String在字符串池中用於可重用性,所以很有可能它會長時間保留在內存中持續時間,這構成了安全威脅。 由於任何有權訪問內存轉儲的人都可以以明文形式找到密碼,這是另一個原因,您應該始終使用加密密碼而不是純文本。 由於字符串是不可變的,所以不能更改字符串的內容,因為任何更改都會產生新的字符串,而如果你使用char [],你仍然可以將所有元素設置為空白或零。 因此,在字符數組中存儲密碼可以明顯降低竊取密碼的安全風險。

2. Java本身建議使用JPasswordField的getPassword()方法,該方法返回一個char []和不推薦使用的getText()方法,該方法以明文形式返回密碼,說明安全原因。 很好地遵循Java團隊的建議並堅持標準而不是反對它。

3.使用String時,始終存在在日誌文件或控制台中打印純文本的風險,但如果使用Array,則不會打印數組的內容,而是打印其內存位置。 雖然不是一個真正的原因,但仍然有意義。

    String strPassword="Unknown";
    char[] charPassword= new char[]{'U','n','k','w','o','n'};
    System.out.println("String password: " + strPassword);
    System.out.println("Character password: " + charPassword);

    String password: Unknown
    Character password: [[email protected]

參考來自: http://javarevisited.blogspot.com/2012/03/why-character-array-is-better-than.htmlhttp://javarevisited.blogspot.com/2012/03/why-character-array-is-better-than.html希望這會http://javarevisited.blogspot.com/2012/03/why-character-array-is-better-than.html幫助。


除非你在使用後手動清理它,否則char數組沒有給你vs String,我沒有看到任何人真正這樣做。 所以對我來說char [] vs String的偏好有點誇張。

看看here 廣泛使用的 Spring Security庫here並問自己 - Spring Security人員不稱職或char []密碼只是沒有多大意義。 當一些討厭的黑客抓住你的RAM的內存轉儲時,即使你使用複雜的方法隱藏它們,也要確保她將獲得所有密碼。

但是,Java一直在變化, Java 8的字符串重複數據刪除功能等一些可怕的功能可能會在您不知情的情況下實施String對象。 但這是不同的對話。


1)因為如果你將密碼存儲為純文本字符串在Java中是不可變的,它將在內存中可用,直到垃圾收集器清除它並且因為String在字符串池中用於可重用性,它很可能會保留在內存中持續時間長,構成安全威脅。由於任何有權訪問內存轉儲的人都可以以明文形式找到密碼,這是另一個原因,您應始終使用加密密碼而不是純文本。由於字符串是不可變的,所以不能更改字符串的內容,因為任何更改都會產生新的字符串,而如果你使用char [],你仍然可以將所有元素設置為空白或零。因此,在字符數組中存儲密碼可以降低竊取密碼的安全風險。

2)Java本身建議使用JPasswordField的getPassword()方法,它返回一個char []和不推薦使用的getText()方法,它以明文形式返回密碼,說明安全原因。遵循Java團隊的建議並堅持標準而不是反對它是很好的。


java中的字符串是不可變的。因此,每當創建一個字符串時,它將保留在內存中,直到它被垃圾收集。所以任何有權訪問內存的人都可以讀取字符串的值。
如果修改了字符串的值,那麼它將最終創建一個新字符串。因此,原始值和修改後的值都會保留在內存中,直到它被垃圾回收。

使用字符數組,一旦提供密碼的目的,就可以修改或刪除數組的內容。修改後甚至在垃圾收集開始之前,內存中將找不到數組的原始內容。

由於安全問題,最好將密碼存儲為字符數組。


字符串是不可變的,它將轉到字符串池。一旦編寫,就無法覆蓋。

char[] 是一個數組,您應該在使用密碼後覆蓋它,這是應該如何完成的:

char[] passw = request.getPassword().toCharArray()
if (comparePasswords(dbPassword, passw) {
 allowUser = true;
 cleanPassword(passw);
 cleanPassword(dbPassword);
 passw=null;
}

private static void cleanPassword (char[] pass) {
 for (char ch: pass) {
  ch = null;
 }
}

攻擊者可以使用它的一種情況是崩潰轉儲 - 當JVM崩潰並生成內存轉儲時 - 您將能夠看到密碼。

這不一定是惡意的外部攻擊者。這可以是支持用戶,可以訪問服務器以進行監視。他可以查看故障轉儲並找到密碼。


簡短而直截了當的答案是因為char[]String對像不可變時是可變的。

Strings在Java中是不可變對象。這就是為什麼它們一旦創建就無法修改的原因,因此從內存中刪除內容的唯一方法就是讓它們被垃圾收集。只有這樣,當對象釋放的內存才能被覆蓋時,數據才會消失。

現在Java中的垃圾收集不會在任何保證的時間間隔內發生。因此String可以在內存中持續很長時間,並且如果進程在此期間崩潰,則字符串的內容可能最終在內存轉儲或某些日誌中。

使用字符數組,您可以讀取密碼,盡快完成密碼,然後立即更改內容。





char