14

I am creating a rails application that needs to store a large amount of sensitive data. To assure my customers that the data is being protected, I want to encrypt it on a per-user basis. I have done research looking for gems that can accomplish this. So far I've found strongbox and safe. Together, this would seem to provide a solution for me.

However, I am wondering if this is a common practice. It would seem that most rails applications have some sensitive data to store regarding their users. AuthLogic is handling my password encryption, but emails and other personal data are just as sensitive. Is it common practice to leave these items unencrypted in the database and assume that it will never be compromised? I understand that the database resides in an area that can not communicate with the outside world, but a determined attacker could easily compromise this. Is it common practice for Rails developers leave their data unencrypted and simply trust the security of their web server?

4
  • This question is not rails or implementation specific. You would probably benefit from migrating to Security.stackexchange.com
    – Rory Alsop
    Commented Jun 27, 2011 at 14:33
  • @Rory: This question is nearly two years old, so it won't be migrated to another site. Commented Jun 27, 2011 at 18:18
  • @Bill - wups - I didn't even spot that. I was just browsing through the security tag and didn't even pay attention to the date. Sorry.
    – Rory Alsop
    Commented Jun 27, 2011 at 19:04
  • @Rory: It's no problem. If you see anything that's definitely not programming and is only a few months old or less that you'd like migrated, let us know. Commented Jun 27, 2011 at 19:09

3 Answers 3

14

The problem with encrypting your database is that anything you encrypt cannot be used in a SQL query, and also, it still has to be decrypted before it can be used. This means that you need to place the decryption key in close proximity to the database, and in most cases, if someone can compromise your database, that means they have also compromised your decryption key at the same time. Thus the encryption step has bought you very little. With passwords, no decryption is necessary because it's actually a hash function. You're far better off making sure the database is never compromised in the first place.

Always assume that if a hacker can compromise any portion of your security, they can compromise all of it. Chain is only as strong as its weakest link and all that.

Credit card numbers and social security numbers (which fortunately you don't usually need to index on) are probably the most obvious exception to this, but if you have to ask this question, you've got no business storing those items in the first place. There's all kinds of legal trouble you can get into for messing that stuff up.

5
  • 6
    I think it is bad advice to go against the industry standard of using layered security mechanisms. Your reference to a chain only being as strong as its weakest link doesn't apply to layering of defensive mechanisms. However, your advice to not store any sensitive information unless necessary is good.
    – Peder
    Commented Jun 27, 2011 at 12:27
  • 3
    Bob - a more useful and accurate assumption is: Assume, given enough time, an attacker will compromise a particular security feature. For this reason you use defence in depth, with multiple layers - which helps slow an attack to the point at which you can see it and react.
    – Rory Alsop
    Commented Jun 27, 2011 at 14:32
  • While I concede that defense in depth is a good idea, encrypting the database field means you have to decrypt it too. What encryption/decryption technique do you propose to use that will enable you to let the server access the data securely for legitimate purposes, if you're also assuming that the threat you're trying to protect against is a hacker who has already owned your box?
    – Bob Aman
    Commented Jun 27, 2011 at 19:57
  • if you don't encrypt the data, the hacker only needs to steal your data. If you encrypt the data, the hacker needs to steal both your data and your password. You will hopefully have backups and replicas of your data store, so if only stealing your data is enough then you open up for several unnecessary attack vectors.
    – Peder
    Commented Jun 28, 2011 at 4:39
  • 1
    Whose password though? That's the trick. If it's the end user's password, you have to constantly prompt for the password to access any encrypted information. If you cache the password to the session, that dramatically increases the attack surface, and if you don't, you're prompting the user constantly. Just curious, have you ever built one of these things and had it audited? It's honestly not as simple as you're making it out to be if you also have good UX as a goal.
    – Bob Aman
    Commented Jul 1, 2011 at 23:41
9

Credit card number, SSNs, etc should always be stored encrypted.

Passwords should always be stored encrypted, using a one-way hash. This means that when the user supplies a password, you can determine if it matches what you stored in the DB, but given only the encrypted representation in the DB, you cannot from that determine their password, short of brute force/dictionary attacks.

I find that in my app's, I like to add unencrypted_**** readers and writers to my class, to make dealing with the encrypted representation painless.

class User
  # has db column encrypted_cc_number
  def unencrypted_cc_number
    WhateverEncryptionClassYouUse.decrypt(encrypted_cc_number)
  end
  def unencrypted_cc_number=(val)
    self.encrypted_cc_number = WhateverEncryptionClassYouUse.encrypt(val)
  end
end
6

Using layered security mechanisms and strong cryptography is good practice if you are storing a large amount of sensitive data. It is required by the Payment Card Industry’s Data Security Standard (PCI DSS). I suggest that you read the following guideline document: https://www.pcisecuritystandards.org/pdfs/pci_fs_data_storage.pdf.

You should definitely not "assume that it will never be compromised"

Not the answer you're looking for? Browse other questions tagged or ask your own question.