Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   Secure Strings

Often, String objects are used to contain sensitive data such as a user’s password or credit-card information. Unfortunately, String objects contain an array of characters in memory, and if some un- safe or unmanaged code is allowed to execute, the unsafe/unmanaged code could snoop around the process’s address space, locate the string containing the sensitive information, and use this data in an unauthorized way. Even if the String object is used for just a short time and then garbage collected, the CLR might not immediately reuse the String object’s memory (especially if the String object was in an older generation), leaving the String’s characters in the process’s memory, where the information could be compromised. In addition, because strings are immutable, as you manipulate them, the old copies linger in memory and you end up with different versions of the string scattered all over memory.

Some governmental departments have stringent security requirements that require very specific security guarantees. To meet these requirements, Microsoft added a more secure string class to the FCL: System.Security.SecureString. When you construct a SecureString object, it internally allocates a block of unmanaged memory that contains an array of characters. Unmanaged memory is used so that the garbage collector isn’t aware of it.


These string’s characters are encrypted, protecting the sensitive information from any malicious unsafe/unmanaged code. You can append, insert, remove, or set a character in the secure string by using any of these methods: AppendChar, InsertAt, RemoveAt, and SetAt. Whenever you call any of these methods, internally, the method decrypts the characters, performs the operation in place, and then re-encrypts the characters. This means that the characters are in an unencrypted state for a very short period of time. This also means that the performance of each operation is less than stellar, so you should perform as few of these operations as possible.

The SecureString class implements the IDisposable interface to provide an easy way to deterministically destroy the string’s secured contents. When your application no longer needs the sensitive string information, you simply call SecureString’s Dispose method or use a Secure­ String instance in a using construct. Internally, Dispose zeroes out the contents of the memory buffer to make sure that the sensitive information is not accessible to malicious code, and then the buffer is freed. Internally, a SecureString object has a field to a SafeBuffer-derived object, which maintains the actual string. Because the SafeBuffer class is ultimately derived from Critical­ FinalizerObject, discussed in Chapter 21, “The Managed Heap and Garbage Collection,” the string’s characters are guaranteed to be zeroed out and have its buffer freed when it is finalized. Un- like a String object, when a SecureString object is finalized, the encrypted string’s characters will no longer be in memory.

Now that you know how to create and modify a SecureString object, let’s talk about how to use one. Unfortunately, the most recent FCL has limited support for the SecureString class. In other words, there are only a few methods that accept a SecureString argument. In the .NET Framework 4, you can pass a SecureString as a password when



■ Working with a cryptographic service provider (CSP). See the System.Security.Cryptog­ raphy.CspParameters class.

■ Creating, importing, or exporting an X.509 certificate. See the System.Security.Cryptog­ raphy.X509Certificates.X509Certificate and System.Security.Cryptography. X509Certificates.X509Certificate2 classes.

■ Starting a new process under a specific user account. See the System.Diagnostics. Process and System.Diagnostics.ProcessStartInfo classes.

■ Constructing an event log session. See the System.Diagnostics.Eventing.Reader. EventLogSession class.

■ Using the System.Windows.Controls.PasswordBox control. See this class’s SecurePass­ word property.

Finally, you can create your own methods that can accept a SecureString object parameter.

Inside your method, you must have the SecureString object create an unmanaged memory buffer that contains the decrypted characters before your method uses the buffer. To keep the window of opportunity for malicious code to access the sensitive data as small as possible, your code should re- quire access to the decrypted string for as short a period of time as possible. When finished using the string, your code should zero the buffer and free it as soon as possible. Also, never put the contents


of a SecureString into a String: if you do, the String lives unencrypted in the heap and will not have its characters zeroed out until the memory is reused after a garbage collection. The Secure­ String class does not override the ToString method specifically to avoid exposing the sensitive data (which converting it to a String would do).

Here is some sample code demonstrating how to initialize and use a SecureString (when com- piling this, you’ll need to specify the /unsafe switch to the C# compiler).

 

using System;

using System.Security;

using System.Runtime.InteropServices;

 

public static class Program { public static void Main() {

using (SecureString ss = new SecureString()) { Console.Write("Please enter password: "); while (true) {

ConsoleKeyInfo cki = Console.ReadKey(true); if (cki.Key == ConsoleKey.Enter) break;

 

// Append password characters into the SecureString ss.AppendChar(cki.KeyChar);

Console.Write("*");

}

Console.WriteLine();

 

// Password entered, display it for demonstration purposes DisplaySecureString(ss);

}

// After 'using', the SecureString is Disposed; no sensitive data in memory

}

 

// This method is unsafe because it accesses unmanaged memory private unsafe static void DisplaySecureString(SecureString ss) {

Char* pc = null; try {

// Decrypt the SecureString into an unmanaged memory buffer pc = (Char*) Marshal.SecureStringToCoTaskMemUnicode(ss);

 

// Access the unmanaged memory buffer that

// contains the decrypted SecureString

for (Int32 index = 0; pc[index] != 0; index++) Console.Write(pc[index]);

}

finally {

// Make sure we zero and free the unmanaged memory buffer that contains

// the decrypted SecureString characters if (pc != null)

Marshal.ZeroFreeCoTaskMemUnicode((IntPtr) pc);

}

}

}


The System.Runtime.InteropServices.Marshal class offers five methods that you can call to decrypt a SecureString’s characters into an unmanaged memory buffer. All of these methods are static, all accept a SecureString argument, and all return an IntPtr. Each of these methods has a corresponding method that you must call in order to zero the internal buffer and free it. Table 14-4 shows the System.Runtime.InteropServices.Marshal class’s methods to decrypt a Secure­ String into a memory buffer and the corresponding method to zero and free the buffer.

 

TABLE 14-4Methods of the Marshal Class for Working with Secure Strings

 

Method to Decrypt SecureString to Buffer Method to Zero and Free Buffer
SecureStringToBSTR ZeroFreeBSTR
SecureStringToCoTaskMemAnsi ZeroFreeCoTaskMemAnsi
SecureStringToCoTaskMemUnicode ZeroFreeCoTaskMemUnicode
SecureStringToGlobalAllocAnsi ZeroFreeGlobalAllocAnsi
SecureStringToGlobalAllocUnicode ZeroFreeGlobalAllocUnicode

C HA P T E R 1 5


Date: 2016-03-03; view: 659


<== previous page | next page ==>
Encoding and Decoding Streams of Characters and Bytes | Nbsp;   Enumerated Types
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.007 sec.)