By: Greg Ose
Even with the best intentions, secure storage of sensitive information is a common architectural issue that is typically overlooked by corporations in the development of applications. While you may be using AES with a 256 bit key and can advertise your industry-standard, cutting-edge, crypto-hacker defenses, you still may be exposing you and your customer’s data to significant risk. You need to ask yourself the question: “Where exactly did I leave those keys?”
All too often on pen tests we will obtain significant privileges within a client’s network and while the issues leading to this are completely out of scope for this post, you need to start thinking about what an attacker could compromise once they have free reign of your network. What are your key assets and how are you protecting these? Typically, the answer to the former will include client information, be it PII or credit card related information, and the answer to the later is “we encrypt it.” Unfortunately, “we encrypt it” is usually only completely understood by the handful of developers that wrote the code to do the encryption. They received the requirement specs to do encryption, maybe even detailed enough requirements to specify a well establish crypto algorithm and key size, wrote the code to do that using standard and well regarded libraries, and moved on to the next requirement. But ask yourself, were there any requirements around where the encryption keys should be stored?
During pen tests, once we have established that encrypted information is being stored, the task becomes what algorithm is being used and where are the associated keys? If you know a company is making the effort to encrypt something, it’s probably a decent target to go after. Fortunately for us, and our looming lunch break, there are usually only a handful of places we typically need to look:
The database or configuration file – Usually by the time we have access to encrypted data, we have full access to the host storing the data or running the application. If we only have to look one directory up for a configuration file or at another table in the database for the encryption key, you might as well have base64 or rot13 encoded the data. By the way, this includes any configuration options you may be storing in the registry or other locations on the host.
The application source code – In a compromised environment, source code repositories or file shares containing source archives are always an interesting target. We can start to understand your applications better and figure out exactly how encryption or decryption is being done. If your source code contains hard-coded encryption keys, this process can easily be reversed and executed by us in our own program.
The application binaries / compiled libraries – If your source repository is locked down and access to source is unavailable, compiled application binaries or libraries are always going to be accessible. Even during a short-term pen test, a skilled pentester will be able to throw the mycrypt.dll library into IDA and search for the 32 byte static array you used to store your key. Even more conveniently, a pentester may just be able to import the library and call its decrypt(byte) function for instant decryption.
While these may be the worst-case scenario for storing encryption key, they are what we almost always see in use within corporate environments.
So where should these keys be stored? Unfortunately, there is no clear cut answer for this. This is the most difficult problem when providing encryption in your applications; if decryption needs to be done in an automated fashion (which is almost always a requirement) you need to fully trust the application performing the decryption. Seems like common sense, but how can you trust the application if you assume the environment has been compromised? For this problem, the only option you have is to make obtaining the encryption key harder, though not impossible, for an attacker. A best-case implementation of this involves sending your encrypted data to a HSM, hardware security module, to perform the encryption and decryption of the data. However, you still trust your application and environment to authenticate and access the HSM for this functionality. This process can be obfuscated and expanded to include numerous steps, but ultimately you still run into the core trust issue of the environment. This problem is the same that digital media producers and software publishers have been fighting for years by using DRM protection; their code or media being the equivalent to you or user’s sensitive data.
While not perfect, by removing immediate access to encryption keys and delegating this access to a separate host, you can implement more complete security controls around the host managing encryption keys. For example, if the entire Window’s domain is compromised, you can ensure that the host storing keys is not part of this domain and has limited or preferably no access by users. In-house at Neohapsis, we are working on developing an easy to use, open-source, server that can be utilized to provide this out-of-band key management. This will be an extension to existing libraries to provide remote key storage. No promises on when it will be released (sorry, we have to be billable!), but hopefully it will offer developers an easy way to implement better key storage and security within their applications.