Microsoft .Net has an object for safely and securely handling passwords: System.Security.SecureString. “The value of a SecureString object is automatically encrypted, can be modified until your application marks it as read-only, and can be deleted from computer memory by either your application or the .NET Framework garbage collector”, according to the MSDN documentation. As with any security control, however, there are a few ways around it. Consider the following PowerShell and C# code samples.
# Some not-so-secure SecureString from a vendor whitepaper
password = Read-Host -AsSecureString -Prompt “Please provide password”
// Some not-so-secure SecureString code I wrote by mistake
private void button1_Click(object sender, RoutedEventArgs e)
{
secretString = new SecureString();
foreach (char c in textBox1.Text.ToCharArray()) { secretString.AppendChar(c); }
textBox1.Text = “”;
}
Try the samples above. Use something like Mandiant’s Memoryze or AcessData FTK Imager to get a copy of your current Windows memory. Search the memory for your password and, sure enough, you will find it in clear text. Sometimes, as with the C# code, you will find your password several times over.
What happened? In both cases, the value was passed to the SecureString in clear text. The SecureString is encrypted, however, the original input is not. That input value may stay in memory for a long time (depending what the underlying Windows OS is doing.)
Below are some examples of populating a SecureString in such a way that the password is not exposed in clear text. A the saying goes, trust but verify. In this case, trust the method but check using Memoryze or Imager to be certain.
# A secure SecureString implementation
$password = New-Object System.Security.SecureString
do {
$key = $host.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”)
if ($key.Character -eq 13) { break }
$password.AppendChar($key.Character)
} while (1 -eq 1)
// A more SecureString code example
private void button1_Click(object sender, RoutedEventArgs e)
{
secretString = passwordBox.SecurePassword;
passwordBox1.Clear();
}