Protect your passwords - The SecureString Class

The SecureString Class was created to hold sensitive information such as passwords, credit cards, SSNs, etc ... and is located in the System.Security namespace.  It is an extra layer of security to keep prying eyes away on a compromised machine.

What is wrong with using the standard String class for secret information?

  • Strings are not encrypted - so anyone or anything (Malware or Viruses) who have access to your process memory can view the values
  • Strings are immutable - when a String is modified, a new String object is created, leaving two copies on the heap
  • Strings are not pinned - Garbage collection can move the String object around in memory
  • Strings cannot be scheduled for disposal

The SecureString Class solves each of these

  • The SecureString class is encrypted using DPAPI, a data protection api.  The problem with DPAPI is that it is platform dependant.  It is only included in Windows 2000 sp3 and later. 
  • Only one instance of the SecureString object lives in memory
  • You can clear the object when finished and the memory is actually zeroed out
  • Provides a locking mechanism so other code cannot modify the object - MakeReadOnly method

Example (Console application):

Remember to import the System.Security namespace.

        static void Main(string[] args)
        {
            SecureString secureString = new SecureString();

            //the following input code is from http://blogs.msdn.com/shawnfa/
archive/2004/05/27/143254.aspx
            // get the first character of the password
            ConsoleKeyInfo nextKey = Console.ReadKey(true);

            while (nextKey.Key != ConsoleKey.Enter)
            {
                if (nextKey.Key == ConsoleKey.Backspace)
                {
                    if (secureString.Length > 0)
                    {
                        secureString.RemoveAt(secureString.Length - 1);

                        // erase the last * as well
                        Console.Write(nextKey.KeyChar);
                        Console.Write(" ");
                        Console.Write(nextKey.KeyChar);
                    }
                }
                else
                {
                    secureString.AppendChar(nextKey.KeyChar);
                    Console.Write("*");
                }

                nextKey = Console.ReadKey(true);
            }

            //set readonly
            secureString.MakeReadOnly();

            //need password again
            //decrypt
            IntPtr ptr = Marshal.SecureStringToBSTR(secureString);

            //retrieve string - unsecure
            Console.WriteLine(Marshal.PtrToStringBSTR(ptr));
     
            //zero out memory
            Marshal.ZeroFreeBSTR(ptr);
         
            //clear SecureString
            secureString.Dispose();
                    
        }

One thing to note is that once the MakeReadOnly method is called, the Clear method cannot be called; at this time you should use the Dispose method.  Once the SecureString is made readonly, it cannot be undone.

Some of you may be saying this isn't secure! Your right. The section where the pointer is written to the console is unsecure because the SecureStringToBSTR method creates a String object, but this is just an example, not how it should be used.

The SecureString is available to secure data that should never be represented strings.  It is only really available in a few areas and only makes sense for apis that take advantage of it.  One api that takes advantage of this is CredUIPromptForCredentials where a SecureString object is returned for the password and can be used to start a process where the ProcessInfo class accepts the SecureString object.

There are some problems with the SecureString Class.  It does not protect you from users with a debugger.  Hawkeye, a nasty hacker tool but a great developer tool, can decrypt the SecureString objects and its Open Source!  It simply isn't supported in many apis.  However, it does protect from a dump file containing the heap from a crash (how many passwords are found).  Note that most Malware and Viruses have this privilege because they run under administrator.

I think that when more apis take advantage of this object, it will be a great tool.  Glav created a SecureTextBox control for use in forms applications.  It really would be useful if ConnectionStrings were handled in this manner.  It really is of no use for logging in on an Asp.Net application.


Posted by: kjsteuer
Posted on: 4/18/2008 at 2:27 PM
Tags: , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed