I am considering encrypting my database and/or encrypting only certain columns in a few tables. Is it worth the time? I mean, how much of a burden would it be on someone if they were to get a hold of my encrypted database? Has anyone even found a way to break this?
If you are interested in using column level encryption in SQL Server 2005 and higher I have a bunch of sample code of how to use the built in encryption features in SQL Server to secure sensitive data. The code is all available at http://sqlcrypto.codeplex.com/
In the code I show how to encrypt sensitive data and ensure that only authorized users can decrypt it. I take advantage of the built in key management functionality and have strong randomly generated symmetric AES key managed by the database engine and those AES keys are then secured with certificates. Database roles control who has access to which keys and with the built in SQL Server encryption you can even use passphrases to additionally secure keys or certificates so that you don't even have to trust your DBA if the data is that highly sensitive. Having said that, if you don't trust your DBA then you have other problems :)
Since SQL Server does the right things with encryption (ensuring unique IVs) you cannot search encrypted columns without doing a table scan and decrypting every row to see if there is a match. I provide some sample code for building an HMAC of encrypted data so that you can at least do a basic search without leaking cleartext information.
I also have examples of how to store salted, stretched hashes of passwords using both the built in hashing algorithms (which are insufficient for production use) and a SQLCLR implementation of the bCrypt hashing algorithm for much better password storage.
There is also some sample code to show the use of transparent data encryption to encrypt the full contents of your data and log files on disk.
Some of the advantages to using the built in encryption are:
- Great key management, the server does the right thing when generating encryption keys and uses multiple levels of encryption to protect the keys
- Correct encryption the server ensures that every piece of data is encrypted with a nonce IV every time it is written, that means that someone cannot look at two encrypted values and determine that they are identical cleartext values.
- Optional integrity checking of encrypted columns to ensure that someone cannot just overwrite an encrypted value with another encrypted value
- Portability, you can access your data from multiple platforms without having to deal with headaches of differences in the platform implementations working differently.
- Good data at rest security, the encryption is done before any log or data pages are written to disk so any data logged does not contain cleartext.
- Ability to easily follow the principle of least privilege and only grant access to encryption keys to roles and/or users who require them.
Edit: For Microsoft SQL Server specific information, read @Joe's comment below. Also,
I expect while the feature you describe encrypts the binlogs (or similar, as in for intrusion to the filesystem), it would probably not help if someone gained access to the data using SQL injection, because of the automatic nature of the decryption. I think you should either box the sensitive information into a separate SQL user (and restrict from the main user), alternatively you could add an additional layer of encryption/hashing.
Not to mention double-checking your SQL injection prevention.
As mentioned, encrypted databases are computationally more expensive, not to mention the programming effort.
A few suggestions
As mentioned already, do encrypt sensitive information like passwords (which could be used to get to more sensitive information on other accounts), or credit card numbers, SSNs (of course). If you don't need to decrypt (for example, just to compare one encrypted password with the one on file, you don't need to decrypt) then use a hash function.
For SQL injection risk reduction, look at boxing your SQL user access. The authentication parts of your system can be separate from the rest of the system. This may be a much smaller amount of code that is more carefully reviewed and less frequently modified.
If you encrypt the data using a strong and recommended routine, such as AES, and a full length random key (not just a simple pass phrase), then the data becomes useless without the key, except for the basics like you can detect duplicates, you can count rows, see how it relates to unencrypted information, etc.
The intruder may gain access to more than the database. If the intruder gains access to your database and the key (for example, if it is hard-coded into your program), then it is pretty much not effective. If you want, you can consider a complex model that prevents storage of the key in plain. This of course is highly involved if you are retrofitting an existing system.
Don't use the SQL built-in encryption functions. You would run into a similar problem if an intruder gains access to your database and the binlogs. (SQL statement logs, for example in MySQL) The SQL built-in routines are evaluated after the statement, with parameters in plain is copied to binlogs. You should stick to in-program encryption to prevent this leak of the plain version, which find its way into statement-logs (bin-logs, slow-logs), also could leak into the processlist.
- You should ensure there is no SQL injection first.
And other more obvious vulnerabilities. Hardening your outer shell seems like a more economical investment.
- Patching your web-facing services,
- disabling unused access doors,
- also including an access list is a good idea to prevent non-trusted IP addresses, or non-VPN users from exploiting vulnerabilites (not to mention that it can reduce load which helps against Denial of Service attacks)
Encryption is a potentially valuable subsequent line of defense / liability reduction.
But even the complex model I referred to is only as strong as the weakest link.
- Many people really use just a single word for their password,
and you may find you are missing something, like
- not using a slow-enough hash routine, or
- not anticipating that the intruder could rent a cracking cluster for a short time.
But you should still make a best effort.
Ideally, your computers would only give out what is permitted, and encryption of storage would be pointless. This is rarely the case.
Note that this answer only focuses on direct hacking, and not physical access, or access through one of your sysadmin's PCs.
Cryptography is often not the problem. In most cases encrypting the entire database is almost certainly a waste of time.
There are often very important values that should be encrypted. An a value that is often overlooked is the session id, csrf tokens, the password salt and forgotten password token. If you are foolish enough to store your session id in the database then an hacker with a SQL Injection flaw can pull this value out and login without needing to crack a password hash.
As other users already said, encrypting the whole database is probably overkill, meaning that you would lose too much performance while gaining little extra security, since you would encrypt fields which is not necessary to encrypt.
Think about it this way: imagine that an attacker has managed to access all the data in your database thanks to an SQL injection. Which information should the attacker absolutely not see and which information is instead not so important, meaning that even if he could read it, he couldn't do anything with it? An example of the first type would be the users' passwords, and one of the many examples of the second type could be the user's favourite color, if for some reason you need to store this information in the database :D
So, encrypting the whole database is not worth the time and the performance loss, but there are some fields that absolutely need to be encrypted (passwords, credit card numbers, SSNs, session IDs and you could also add personal user information to this list, like phone numbers etc, your users would be grateful for this :) ).
Don't forget that if the attacker has access to your database, he could eventually get access to all the information in it even if some fields have been encrypted, he just needs more time to do it. And if you have very important information in your database, this extra time is extremely important.
And finally a suggestion: invest time into preventing SQL injection attacks. This is probably the most used technique with which an attacker can illegitimately have access to your database.
It depends. Remember that attackers will always target the weakest security link in your system. Do you think unencrypted database data is the weakest link in your system? It seems somewhat unlikely. While it will certainly provide extra protection, your time is probably better spent protecting other parts of your system, that are more likely to be the security weakest link.
Also, keep in mind that encrypting a DB is generally pretty expensive, computationally speaking. If your DB serves a lot of data to a lot of clients, this could really slow down your system.