3.18.2012

T5WTPYAFGP - Encrypt Sensitive Information

At South by Southwest this year, during my talk Defense Against The Dark Arts - ESAPI I covered the "Top 5 Ways To Protect Your Application From Getting Pwnd" [T5WTPYAFGP]. After a couple offline conversations I decided that this would make an excellent series of follow-up blog posts so what follows is the adaptation of that presentation material from that talk. Unlike a lot of other Top-N lists, the goal of this one is not to iterate the flaws, but rather to iterate the solutions.

Additionally each post includes some samples on how you can use ESAPI to implement the solutions discussed and gives us the opportunity to dive into each area a little deeper than we were able to in a one-hour presentation.


You can use the navigation below to navigate between each of the posts.

[5] Encrypt Sensitive Information [current]
[4] Become Big Brother
[3] Fix Your URL

5. Encrypt Sensitive Information
Number five on our list is to encrypt sensitive information. To understand this one we first need to define what actually constitutes sensitive information.

Most organizations that store credit card numbers are (hopefully) storing those credit card numbers in an encrypted format already, but what about the rest of the information that is stored. Think about your own organization or application - what information do you collect from your users?

According to published information, anything that is personally identifiable information, financial information, or medical information is to considered sensitive data and should be treated accordingly. Any organization that has to deal with standards verification will generally check the box for storage of sensitive information as long as that information is stored on an encrypted volume. This protects your customers from physical theft but what about run-time theft, which accounts for most of the largest breaches that occurred last year.

The key is to examine the risk for your application, determine what information would be damaging to release for your customers, and encrypt that data at rest. A lot of organizations simply don't want to incur the performance penalties of performing encryption and decryption of client data but some things are simply too important to ignore.

There are a number of ways to help mitigate the performance impact of using encryption in an application  and we will cover a few of them in this post.

The important thing is that once you have encryption configured (ie you have selected a provider and algorythm) actually performing the encryption and decryption of sensitive information is incredibly simple.

// Populate User Object from Request
// ...
// Encrypt Sensitive Information
CipherText encryptedSSN = ESAPI.encryptor().encrypt(new PlainText(userInfo.getSSN()));
userInfo.setSSN(new String(encryptedSSN.asPortableSerializedByteArray());
// Persist User Object
// ...

To decrypt the data is just as simple.
// Retrieve persisted User Object
// ...
// Decrypt Sensitive Information
CipherText encryptedSSN = CipherText.fromPortableSerializedBytes(user.getSSN());
PlainText decryptedSSN = ESAPI.encryptor().decrypt(encryptedSSN);
userInfo.setSSN(decryptedSSN.toString());
// Prepare User Object for use in application
// ...

Of course this can be abstracted into a service, added as an annotation processor in your persistence layer, and altered to be used in a more generic form that meets your specific platform needs. Additionally, depending on the type of information you are dealing with and the perceived risk of that information being leaked - it may make sense for the data to be encrypted all the time until it needs to be viewed or altered on the front end. This approach can also increase performance of the encryption and decryption because you are only ever performing this step when it is needed.

A comprehensive design is a little beyond the scope of this post, but when I do design I like to envision the end goal - that is what will the object I am protecting look like when I am done. To take the concept of the UserInfo object - here is what I envision as the end results:


public class UserInfo implements Serializable {
   private final static long serialVersionID = 1L;

   private Long id;
   private String username;

   // This field will be stored in-memory and persisted as a hashed value using SHA-256 
   @Sensative(type=SensitiveDataProtection.Type.HASH,
              algo=SensitiveDataProtection.Algo.SHA256
              mode=SensitiveDataProtection.Mode.RUNTIME)
   private String password;

   // This field will be stored in-memory and persisted as an encrypted value using the SecretKey "UserData.SSN" for encryption and decryption
   @Sensitive(type=SensitiveDataProtection.Type.ENCRYPTED,
              key="UserData.SSN",
              mode="SensitiveDataProtection.Mode.RUNTIME)
   private String ssn;

   // This field will be persisted as an encrypted value using the Master SecretKey but will be stored in-memory as a PlainText representation
   @Sensitive(type=SensitiveDataProtection.Type.ENCRYPTED,
              mode=SensitiveDataProtection.Mode.PERSIST)
   private String address;
}


This looks pretty simple to implement for a developer and seems to address a lot of design needs, particularly the need to apply encryption only at the point where it is required. Annotations aren't for everyone however, so how can we accomplish a similar design goal without using Annotations?

public class UserInto implements Serializable {
   private final static long serialVersionID = 1L;

   private Long id;
   private String username;

   // This field will be stored in-memory and persisted as a hashed string
   private HashString password;
   // This field will be stored in-memory and persisted as an encrypted string
   private CipherText ssn;
   // This field will be persisted as an encrypted string
   private PlainText address;
}


This example relies on the usage of data-types to specify the behavior of the data. While this breaks some rules in the world of design, it illustrates a possible solution to the problem.

Now do not be fooled into thinking that these solutions are simple to implement, they aren't - however the benefit of centralizing a standard control to perform this work is that you only have to write it once, you only have to maintain it in one place, and every developer of your application doesn't have to understand how the process works, just that it does.

In closing, here are each of the steps you should perform to address this problem and resolve it.

  1. Identify sensitive data in your application
  2. Design and implement a standard and centralized control
  3. Apply encryption to sensitive data in your application
Stay tuned for #4 on our top 5 list "Become Big Brother"!

1 comment:

  1. You described all the details very interestingly. It is cool that you describe.
    d drops

    ReplyDelete