WPF PasswordBox 以 SecureString 存儲密碼(記憶體加密、非托管堆、可銷毀),但實務中常見 SecureString → String 轉換後再驗證/傳輸,引發安全性質疑。
string。| 場景 | 風險等級 | 說明 |
|---|---|---|
| 僅在記憶體中短暫轉換,立即銷毀 | 低 | GC 非確定性回收,字串可能殘留托管堆,但攻擊面窄 |
| 轉換後跨進程傳輸(HTTP/管道/共享記憶體) | 中 | 需 TLS/加密通道,否則明文暴露 |
| 轉換後持久化(日誌、配置檔、資料庫明文) | 極高 | 違背 SecureString 設計初衷,嚴重安全缺陷 |
| 針對 String 進行弱雜湊(MD5/SHA1 無鹽) | 高 | 彩虹表/碰撞攻擊風險,應用 Argon2/bcrypt/PBKDF2 |
// 僅在邊界處轉換,用完即銷毀
public bool VerifyPassword(SecureString securePwd, string storedHash)
{
IntPtr bstr = IntPtr.Zero;
try
{
bstr = Marshal.SecureStringToBSTR(securePwd);
string plain = Marshal.PtrToStringBSTR(bstr);
// 使用強雜湊驗證
return Argon2.Verify(storedHash, plain);
}
finally
{
if (bstr != IntPtr.Zero) Marshal.ZeroFreeBSTR(bstr);
// plain 變量離開作用域等待 GC,敏感場景可考慮 unsafe 手動清零
}
}
SqlConnection 支援 SecureString 密碼屬性,避免轉換。GCHandle.Alloc(bytes, GCHandleType.Pinned) + RtlZeroMemory 手動清零,配合 [SuppressUnmanagedCodeSecurity]。轉 String 本身不等於不安全,關鍵在於「轉換後怎麼用、存多久、傳多遠」。遵循最小暴露原則:邊界轉換、強雜湊、加密傳輸、即時銷毀、審計日誌脫敏。單純依賴某種技術(如 SecureString)並不能保證絕對安全,威脅建模與纵深防禦才是正道。