19

Cryptography is a widely adopted techonlogy to ensure confidentiality. Not considering implementation flaws, it has a single critical point: the secret key storage. If the secret key is stolen, the whole system will be compromised.

EDIT :

let me specify the context to make the question less broad:

  1. here a java web application is addressed
  2. more specifically it is used the spring framework version 3
  3. spring security 3.1 is used to secure the application
  4. a mysql5 database is available
  5. the application server is tomcat6 or tomcat7
  6. the server machine is not under my control

Maybe the questions can be focused on this scenario but, as pointed out, the problem of the secret key storage is transversal to the adopted technologies. However some libraries might offer peculiar features that can somehow facilitate the work. A clear point is that a tradeoff has to be found between security and the need to do practical things. To complete the analysis it is obvious that the required security level depends on the value of information to secure. It is senseless to flip our minds to enforce super-secure strategies (demanding a very lot of efforts) to keep secret the shoe size of a customer.

Here, I have to secure an email password (that will be stored in a db). I consider this information average critical.

What I'm looking for here, is the best solution with reasonable effort.

So the question is very clear: where would you store this information?

  1. do you store it in a database? So it should be encrypted and this requires another key (and where do you store this second key?)
  2. do you store it inside the .war package? How do you prevent unauthorized accesses to the sources?
  3. do you adopt a different strategy?

motivations for your strategy will be appreciated. thank you

MaVVamaldo
  • 2,505
  • 7
  • 28
  • 50
  • 2
    See also "Where do I securely store the key for a system where the source is visible?" http://security.stackexchange.com/questions/5994/where-do-i-securely-store-the-key-for-a-system-where-the-source-is-visible, and "Best practice for password-protecting a secret key" http://security.stackexchange.com/questions/20076/best-practice-for-password-protecting-a-secret-key, – David J. Liszewski Dec 21 '12 at 13:42
  • This depends so much on the use case and environment that this is impossible to answer in any meaningful way; buy a book on key management instead. – Maarten Bodewes Dec 21 '12 at 19:22

2 Answers2

12

I take the liberty to write an answer even if this doesn't have anything to do with a Java Web Application: I think the problem exists in only minor variance with all platforms.

Basically there are 3 candidates for key storage, the first 2 of which you mentioned:

  • The DB
  • The App ("hardcoded")
  • Somewhere else on the server, that runs the WebApp, most often a file

You already put your finger on the weak points of the first 2, so no need to repeat, I fully agree.

This is also the motivation for me to use the third candidate. The reasoning is this:

  • Different instances of the same app can easily have different keys, so a compromise of one will not automatically spread to all others
  • If the server is compromised in a way, that allows the attacker to read any file, it is game over anyway: You wouldn't be able to stop him from reading the app binary or the DB
  • File system security on a web server is a quite well-understood subject
  • Break-ins, that allow full filesystem access are statistically much less often, than application or database break-ins
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
  • ok, so you say to create a file in the file system of the server machine and to write there the password in plaintext. Of course, I have to set up strict permission on that file (only the "application-user" can read it, for example). A common scenario is the one in which the server machine is not under your control. The admin user could do everything anyway. Maybe the file with the key might be encrypted with a client side key. But it will imply a more complex architecture which is not always available. Ok, we can't but trust the provider. – MaVVamaldo Dec 21 '12 at 14:15
  • 2
    Putting the key into a file (or a container as was suggested by @AleksanderGralak) can be done with our without additional steps, such as encrypting the key with a hardcoded key. A rogue Admin is the same as a successfull root-level attacker: NOTHING is safe from him – Eugen Rieck Dec 21 '12 at 15:53
  • Two issues with using a file that I can see: 1) you have to keep this file duplicated (or more) and in sync if your application gets big enough to require more than one load balanced instance. 2) If you have a huge number of users then searching the file can become a burden. I don't profess to be an expert in this, but it is some of the thoughts I have had when trying to figure this out for myself just now. But this is one of the few posts I have seen to give me clues that others are looking or making the same solutions. – Bill Rosmus Nov 28 '14 at 07:21
  • You have to keep **all** files synchronized, that make up the application - nothing new here! Concerning the user count: The file is tiny and most likely in RAM (cached), so no IO issue. Additionally you can parse it on App startup once and keep a parsed copy around! – Eugen Rieck Nov 28 '14 at 20:05
7

No matter what you always need to store somewhere the secret key. Even if you decide (which is silly) that you provide key manually, then the key resides in memory and someone can find it.

Where you store it depends on your choice. However it should not be in plain text. So if you store a key in database, then use hard-coded secondary key in application. So if intruder has only access to db, then the encrypted main key is protected.

I would go for application configuration to store secondary key in container. That way only your application will have access to this properties. So the attacker will have to take control over your application or container to get access to that key.

So assuming following scenarios:

  1. Your application get hacked: attacker has the same permissions as you have. One can try to use your API to get sensitive information without playing at all with encryption. Your code will do it for them. Next option: she can try to get your war file or class files and decompile them to find out the hard-coded key, or learn about encryption mechanism you used.
  2. Only database is hacked: you should be fine having data encrypted with the key that is not in database itself.

To make it harder for attacker. You can place file in file system. As described in other answer add appropriate FS permissions to it. But additionally use java Security Manager to restrict access for all java classes except the one that really needs to read it. Also restricting modification to your jar and class files would be a good idea.

The more locks you have the more secure you are. As it is with standard door lock. The locks should be from different vendors and with different mechanisms. But at the end the skilled burglar will get into anyway.

Aleksander Gralak
  • 1,509
  • 10
  • 26
  • @Alexsander: do you have any tutorial how we can implement this in java? How to store secondy key in container and how both secondry and promary key can encrypt data in db. – anand Sep 13 '16 at 16:13
  • Also how can we restrict file system permissions of files for different users in java? – anand Sep 13 '16 at 16:15
  • @Alien01 Just to clarify. Encrypting whole database is out of scope of this issue and as far as I know it is more experimental idea then real thing. So in our situation a secret is a password for email. So you store encryption key in application context: http://stackoverflow.com/questions/372686/how-can-i-specify-system-properties-in-tomcat-configuration-on-startup then you use symmetric encryption to encrypt the password. Now you can retrieve the password from db and decrypt it and use for accessing SMTP server. – Aleksander Gralak Sep 14 '16 at 09:02
  • @Alien01 if you are really paranoiac then you can have secondary key somewhere in file system. So you use first key to encrypt password, then you use secondary key to encrypt already encrypted message and the result you store in db. To retrieve password you do it in opposite direction. To protect file access in fs you can limit read option to only one class. The instruction to setting up permissions in Tomcat: https://tomcat.apache.org/tomcat-7.0-doc/security-manager-howto.html – Aleksander Gralak Sep 14 '16 at 09:06