Sensitive Data

patterns & practices Developer Center

Sensitive data usually needs to be protected in persistent storage, in memory, and while it is on the network. Wherever possible, look for opportunities to avoid storing sensitive data. Use encryption to make sure that sensitive data cannot be viewed.

Follow these guidelines to help protect sensitive data:

Avoid plain-text passwords or other sensitive data in configuration files

Avoid putting any sensitive information in the configuration files or within code. If you have to store user credentials or any other sensitive information in the configuration sections, encrypt the configuration sections by using one of the protected configuration providers. The sensitive information should not be stored in plain text, because an attacker that can compromise a server will be able to read those credentials unless they are adequately protected.

In the .NET Framework version 2.0 and later, there are two libraries that provide encryption facilities for connection strings: DPAPI and RSA. If your application is deployed in a Web farm, you should use the RSA protected configuration provider because of the ease with which RSA keys can be exported. Otherwise, you should use the DPAPI protected configuration provider.

Additional Resources

Use platform features to manage keys where possible

Use platform features where possible to avoid managing keys yourself. For example, by using DPAPI, the encryption key is derived from an account's password, so Windows handles this for you.

Protect sensitive data over the network

Protect sensitive data when it is transmitted over the network. Consider where items of sensitive data, such as credentials and application-specific data, are transmitted over a network link. Using a safe protocol to transmit information is important because it adds protection against inadvertent eavesdropping and modification during transport.

If you need to send sensitive data between the client and WCF service, consider using message or transport security. If you need to protect server-to-server communication, such as between your WCF service and a Microsoft SQL Server® database, consider Internet Protocol Security (IPSec) or SSL.

Do not cache sensitive data

If your service method contains data that is sensitive, such as a password, credit card number, or account status, it should not be cached. If sensitive data is cached on the client machine, it has serious security implications because it leaves interesting data available to attackers.

Perform the following steps to ensure that sensitive data is not cached:

  1. Review operations for sensitive data. Review all of your operations for usage of sensitive data. This could include but is not limited to:
    • Information that either contains personally identifiable information (PII) or can be used to derive PII that should not be shared with users
    • Information that a user provides that they would not want shared with other users of the application
    • Information that comes from an external trusted source that is not designed to be shared with users
  2. Review the operations for caching of sensitive data. Review how each operation manages sensitive data and ensure that it is not cached. There are three patterns of sensitive data caching that you can review for:
    • Custom caching code such as use of a Dictionary or SortedList object
    • Use of the ASP.NET cache via System.Web.Caching.Cache.
    • Use of an Enterprise Library caching block

Minimize exposure of secrets in memory

When manipulating secrets, consider how the secret data is stored in memory. How long is the secret data retained in cleartext format? Cleartext secrets held in your process address space are vulnerable if an attacker is able to probe your application's address space. Also, if the page of memory containing the secret is swapped out to the page file, the secret data is vulnerable if someone gains access to the page file. Similarly, cleartext secrets held in memory appear in the crash dump file if a process crashes.

To minimize the exposure of secrets in memory, consider the following measures:

  • Avoid creating multiple copies of the secret. Having multiple copies of the secret data increases your attack surface. Pass references to secret data instead of making copies of the data. Also realize that if you store secrets in immutable System.String objects, a new copy is created after each string manipulation.
  • Keep the secret encrypted for as long as possible. Decrypt the data at the last possible moment before you need to use the secret.
  • Clean the clear-text version of the secret as soon as you can. Replace the cleartext copy of the secret data with zeros as soon as you have finished with it.

Prior to .NET Framework 2.0, the use of byte arrays was recommended to help implement these guidelines. Byte arrays can be pinned in memory, encrypted, and replaced with zeros. In .NET Framework 2.0, use SecureString instead.

Be aware that basicHttpBinding will not protect sensitive data by default

If you use basicHttpBinding, be aware that message security and transport security are turned off by default. All of the bindings, except for basicHttpBinding, have either message or transport security turned on by default. If you want to secure your WCF messages on the network, you will need to explicitly turn on either message or transport security for basicHttpBinding.

Additional Resources

Use appropriately sized keys

Choosing a key size represents a trade-off between performance and security. If you choose a key that is too small, the data that you thought was well-protected can be vulnerable to attack. If you choose a key that is too large, your system will be subject to a performance impact without a commensurate real-world improvement in security. The appropriate key size changes based on the cryptographic algorithm in use, and also changes over time as machine processing speeds increase and attack techniques become more sophisticated.

The following recommendations will give you a margin of safety without sacrificing too much performance:

  • When you use an asymmetric algorithm (RSA), choose a 2048-bit key
  • When you use a symmetric algorithm (AES), choose a 128-bit key