9

Are there any security best practices for using Rails and Heroku Postgres with pgcrypto's public key PGP.

The naive and direct way seems to be to store the private key and password using Heroku's ENV variables. However this seems like it doesn't add much security since both values are now easily accessed by anyone with access to the environment.

The goal of this would be to encrypt any privacy concerned information such as SIN numbers appropriately.

Scenario:

Let's presume you have some fields that, for some generic regulatory privacy requirement, are required or recommended to be stored encrypted, such as government IDs (SIN numbers for example). What is an appropriate or even common process for encrypting this information using pgcrypto.

If someone has an alternative suggestion for a scenario I'd be glad to include that as well.

Chris Nicola
  • 14,384
  • 6
  • 47
  • 61
  • 1
    Encryption shouldn't be the goal. It should be a means. What/who are you trying to protect against? Are you worried about Heroku staff snooping? Are you worried about someone hacking your app? Does Heroku store database backups separately from any files that might be backed up. – Richard Huxton Jun 30 '14 at 19:32
  • 2
    Realistically I'm not "worried" about Heroku staff snooping but ideally I'd like to ensure data that should be absolutely private has a reasonable chance of remaining so. It's also about following security and data privacy best practices here if there are any that can be defined. – Chris Nicola Jun 30 '14 at 21:04
  • Best practice AFAIK is to evaluate what threats pose what risks and decide how much effort is required to defend against them. I'm not sure that "should"..."absolutely"..."reasonable" belong together. – Richard Huxton Jun 30 '14 at 21:21
  • Please see http://stackoverflow.com/q/8054503/398670, http://dba.stackexchange.com/q/24370/7788, http://stackoverflow.com/q/12614523/398670, http://stackoverflow.com/q/21095026/398670 and lots of others. I agree with Richard - there's no easy answer, no canned "how you should do it". There is no perfect security. Model your threats. Figure out what you're trying to protect against. Define acceptable risks. Identify any legal standards you must comply with. *Then* design the system around those requirements, with the corresponding trade-offs in manageability, uptime, etc. – Craig Ringer Jul 01 '14 at 02:03
  • I think you misunderstand my intention here. I'm not asking for "perfect" that isn't what I'm meaning when asking about "best practices" is. I'm asking if there is a fairly standard or even somewhat widely accepted way to implement column PGP encruption with pgcrypto and suggestions for how to protect the keys. Or does everyone just sort of wing it? At a minimum I'm looking for people to describe ways in which they have implemented this themselves in the past and why they made the decisions they did. – Chris Nicola Jul 04 '14 at 17:31

2 Answers2

4

This question doesn't have an answer until you define your threat model, but your question suggests that you want to store information in a way that even people with access to the server environment can't read it, in which case there are really only these options:

  1. Don't store the data at all. Depending on what you need the data for you may be able to avoid storing it on your own servers for any reason. For instance, you can ask a user to enter their credit card number and immediately forward it to the credit card processor without saving it (which means you will need to ask them for the number again next time, unless the credit card processor hangs on to it for you.) Some payment processing schemes even send the payment data directly to the processor so that your website doesn't have to touch that data at all. Depending on your requirements this may or may not suit your needs.

  2. Store the data only as a hash, like a password. This is useful if you don't actually need the data, but only need to verify that someone using your site has the data. This is universally the solution for passwords and other "secrets" but is useless for other data.

  3. Store the data with public/private encryption, and don't keep the private key on the server at all. This could work if, for instance, the server has the public key in its environment, with which it saves data to the table, but an administrator has to download the encrypted data and decrypt it locally in order to use it. Again, this has severe limitations so you can only use it if your requirements of what to do with the data are compatible.

  4. Store the data with client-side symmetric encryption, encrypted and decrypted only with a client key. This is how e.g. LastPass works. It means that you, the server admin, can not do anything with the data except return it to the user that submitted it. Once again, this only works if your requirements are very narrow.

If your requirements for what you do with the data are not compatible with any of the above, then you have no recourse. You could encrypt the data with symmetric encryption and keep the key in the server environment as a guard against backups or access to the database, but not the application, falling into the wrong hands, but that does not match the threat model of an attacker with access to the operating environment.

There is no one-size-fits-all "best practice" here because the tradeoffs involved in handling a threat model where the attacker has access to the environment are so great that only applications with very specific, limited requirements can guard against it at all. If the server can read the data, then so can an attacker.

Andrew Gorcester
  • 19,595
  • 7
  • 57
  • 73
  • The question is somewhat hypothetical at the moment. 1 is the primary option whenever it's possible and the data is considered "sensitive". 2 is not an option for this data since it is in all cases necessary to read. 3 is the option I'm interested in as a potential option for sensitive data we do need to keep and need to read and I'm specifically interested in approaches towards protecting the private key and keeping it separate from the server. – Chris Nicola Jul 04 '14 at 23:51
  • You can either keep the private key on your local machine (3) or you can have clients keep the symmetric keys to their own data on their local machines (4). If you need additional detail, what specifically is the problem? – Andrew Gorcester Jul 05 '14 at 00:37
1

Heroku Env

You get some benefit in storing the key in the Heroku env and encrypting in the database because then an attacker can't get the information from the DB either by direct break in or by SQL injection.

You are still vulnerable to anyone who can break into your app server, your Heroku account or any Heroku or Amazon staff that can obtain access to the server.

Separate Secure Server

If you have a large team and or subcontractors that can access your Heroku account you could have a separate server on a separate account or even separate more secure hosting that is reponsible for saving and loading the secrets with only a few highly trusted people having access to it. It could be kept small and simple and only accept requests from your app servers to minimise the attack surface. The server could be designed to limit the rate at which it provided the confidential data from the database to prevent a complete dump being taken rapidly even in the event that your main App server is broken into. It could access the same DB or a different on and perform the encryption/decryption on every load/save request from the app server before passing the result back.

Doing this will add latency and complexity but that is a trade off you can consider against the security gains. To get the secret information in bulk an attacker would have to either break into/have access to the app server and extract the secret data slowly from the secure server without triggering your intrusion detection systems or obtain direct access to your secure server in some way (which should be harder than the main server as there are less accounts to target for social engineering, password guessing and the direct attack surface area should be smaller.).

Joseph Lord
  • 6,446
  • 1
  • 28
  • 32
  • Yes this seems like a good place to start. As I said I'm not concerned about Heroku staff. If the DB data was compromised or a backup it would protect the sensitive fields. The second step of a separate server for loading the secrets is an interesting approach but I'd need more specifics to really understand how that might actually work. – Chris Nicola Jul 12 '14 at 17:18
  • I've updated the answer to try to flesh it out. In many cases the separate server will be overkill and the cost in latency, complexity and in having an additional point of failure will not be worth the security gains. Of course any time you encrypt DB data there is cost, if only in the loss of searchability. – Joseph Lord Jul 14 '14 at 09:17