2013-01-22 27 views
12

所以這個類似乎很少使用:SecureString。至少從2.0版開始,有幾個SO問題,但我想我會問自己的具體問題:安全使用SecureString登錄表格

我有一個LoginForm;帶有用戶名和(被屏蔽的)密碼字段的簡單WinForms對話框。當用戶同時輸入並單擊「登錄」時,信息被傳遞給一個注入的認證類,它執行一層密鑰擴展,然後將一半的擴展密鑰用於驗證,而另一半則是加密用戶的對稱密鑰賬戶數據。當所有這些都完成後,loginForm關閉,處理驗證器類,然後系統繼續加載主表單。相當標準的東西,可能比標準的hash-the-password-and-compare有更多的參與,但是簡單的散列密碼在我的情況下會以明文方式存儲用戶數據,因爲這些數據包括第三方密碼,第三方系統(我們都知道人們喜歡重複使用密碼)。

這是第一個問題;我將如何使用SecureString從密碼文本框中檢索密碼,而不是它通過文本框的Text屬性顯示爲普通的System.String?我假設有一種方法可以訪問由CLR類包裝的文本框的非託管GDI窗口,並使用Marshal類拉取文本數據。我只是不知道如何,我似乎無法找到好的信息。

這是第二個問題;一旦我將密碼作爲SecureString使用,我如何將它從System.Security.Crypto命名空間傳遞給哈希提供程序?我的猜測是,我會使用Marshal.SecureStringToBSTR(),然後Marshal.Copy()從返回的IntPtr返回到一個字節數組。然後,我可以調用Marshal.ZeroBSTR()來清理非託管內存,並且一旦有散列,我就可以用Array.Clear()清零託管數組。如果有一種更清晰的方式可以讓我完全控制內存中任何託管副本的生命週期,請告訴。

第三個問題;所有這些都是非常必要的,或者是在託管內存環境中System.String固有的不安全性有點過分?任何用於存儲密碼,加密或其他方式,應該超出了作用域,並且在操作系統考慮將應用程序交換到虛擬內存之前就已經到達垃圾收集器的路上了(允許從交換文件中嗅探密碼在計算機硬關機後)。冷啓動攻擊是一種理論上的可能性,但真的,這有多常見?更大的擔憂是現在解密的用戶數據,作爲整個應用程序生命週期的用戶的一部分而掛起(因此,除了一些基本用法,它們保持相當休眠狀態外,它們將成爲使用SecureStrings的主要候選項)。

回答

5

如果您認爲您需要SecureString您必須相信攻擊者也可以讀取您的進程內存。如果後者是真的,他可以在輸入密碼時讀取密碼字符,也可以直接從文本框內部字符緩衝區中讀取密碼字符,或從屏幕讀取像素。

這是一個不切實際的情況。請勿使用SecureString。它幫助很少,偷走你的時間。

冷啓動攻擊更真實,但非常罕見。他們需要通常完全擁有機器的物理機器訪問權限。 由攻擊者閱讀是你在這種情況下最擔心的問題。

基本上,你必須設計一個案例,其中你的開發人員時間很好用SecureString

+6

這個想法是減少攻擊面。例如,如果攻擊者無法讀取內存,但可以訪問交換文件,SecureString可以提供幫助。我們無法預測攻擊者可以做什麼或不可以做什麼,所以我們試圖讓事情變得非常困難。但是,沒有任何保護措施會有幫助:如果應用程序知道這些信息 - 攻擊者可能也可以。 –

+0

我猜對於'SecureString'的最佳論據是開發人員的時間最好花在其他地方。 – usr

+2

好吧,我不必相信攻擊者可以看到輸入的字符,相信攻擊者可以提取交換文件。複雜程度和要求的訪問水平是非常不同的。所以,我可以預見SecureString的一個優勢是在一個不需要過多設計的情況下需要長期保存在內存中的敏感數據(比如前面提到的第三方系統憑證,只要應用程序能夠運行並且最終可以結束交換文件)。但我認爲我同意你的觀點,即10倍中的9倍比它的價值更麻煩。 – KeithS

3

首先,我想說明我同意usr - 不要打擾。

我們的細節:

  • This答案提供了討論的大背景。
  • This是一個使用SecureString的TextBox控件。我沒有 使用這個,所以我不能評論的質量,但在MS博客我 不要指望它是什麼,但不正確。
  • 要回答有關將數據傳遞給System.Security.Crypto的問題,基本上,您的 不能,也不會有大量的非託管內存編組將幫助您,因爲在此類編組過程中字符串會被解密。它必須因爲否則它不能被您的目標API使用。如果您使用的是CSP或X509Certificate,則可以使用SecureSctring,因爲它們在框架中受支持,但就是這樣。
+0

我不認爲問題是在解密字符串(不可否認,我的知識很少)。我認爲問題在於生成一個System.String,開發人員無法控制其生命週期;它是在堆上創建的,只要GC沒有收集它(在交換到VM之前可能會發生,也可能不會發生)。一個字節數組OTOH可以就地歸零,並且非託管的IntPtr也可以正確清理並釋放,所有這些都有希望在CPU高速緩存或RAM中,而不是交換文件,因爲它正在被積極使用。 – KeithS

+0

那麼,你不應該真的在計數零字節數組。垃圾收集器隨時隨地刷新內存,可能會有多個字節數組的副本。如果你的目標API被管理,那麼你對後面的類型幾乎沒有任何控制。 –

+0

如果GC的移動內存(正如我所知道的那樣),我希望它在堆優化期間或之後清理本身。我相信GC能夠以一種有效的方式處理內存,因爲如果我想在一個託管的運行時中工作,我就無能爲力了(我這樣做,因爲它比VC++更容易)。但是,我知道GC不在我的叮and聲中,這是在受管運行時編寫安全代碼時的主要問題。 – KeithS