7

I'm developing a web-application that stores sensitive user data. Although the data is sensitive we want it stored permanently because the users might want to come back later and reuse it. The user data must be accessible by the server during a user session.

We can assume that the number of active sessions is low in comparison to the number of datasets permanently stored.

  • Asset: Part of the data stored in the database that is really sensitive - but needs to be processed on the server-side during user-sessions (that's the point of the application) and stored there permanently (for usability reasons).
  • Scenario: A hacker gains access to the database and is able to read all it's data.

NOTE: This is not meant as substitute for a risk-analysis nor any other part of security management, nor is it meant as substitute for certain other measures (password policy, SSL/TLS, audits, … you name it). This is about checking one specific security measure.

Proposed counter-measure: User-data encryption

To mitigate the risk of leaking all of the sensitive data to an attacker gaining access to the database, I'd like to encrypt the data (very similar to option 1 in this question):

  1. During user registration the server generates a user-key U (AES).
  2. The user-key is encrypted with a password derived key (SHA256) d(p) and stored in the database AES(d(p), U).
  3. Every time the user logs in, the key is decrypted and stored in the server-side session storage p -> d(p) + AES(d(p), U) -> U.
  4. The user then is able to work with his/her data as long as the session persists. The data is encrypted with a random AES-key (message key m). The AES-key is then encrypted with the user-key and stored alongside the encrypted data (AES(U, m) + AES(m, data)).

Question 1: Are there any obvious security flaws in that scheme (except that the attacker can access the data of all logged-in users)?


Password-recovery

One obvious flaw of the above scheme is that there is no process to do a password recovery: Once the password is lost, the user-key can't be decrypted and thus the data is lost too.

To work around that we generate another RSA-key-pair (M_pub + M_sec). The public key is part of the application configuration. Additionally to the previous scheme:

  1. a) The user-key and the user-email is encrypted with the master key and stored with the user-record as recovery information RSA(M_pub, U+user.email)

We have another app, on another server that has access to the private master key (but not to the database). The password recovery would then look like this:

  1. The user starts the password recovory as usual (reset password -> email with link to a form).
  2. The user chooses a new password p'.
  3. The original app now asks the password-reset app to decrypt the user-key by sending the recovery info RSA(M_pub, U+user.email) and the new password derived key d(p') to the recovery server.
  4. The password-reset app decrypts the recovery info M_sec + RSA(M_pub, U+user.email) -> U + user.email, sends a notification email to the user.email (telling the user to report the incident if he/she didn't cause the recovery) and sends the newly encrypted user-key AES(d(p'), U) back to the original app.

The recovery-process would be rate-limited so that the number of breached keys is limited until the breach is discovered.

Pros:

  • Password recovery is still immediate.
  • An attacker needs to hack two systems to gain access to the full database.

Cons:

  • An attacker able to gain access to one system is likely to gain access to the password-reset system too.

Question 2: To what point does this way of doing the password recovery reduce the effect of the encryption? (Is it still worth doing?)

Question 3: Are there any other processes that improve data-security (in case of a hacked server) without making an automated password recovery impossible?

  • Can you use a Hardware Security Module? – Anonymous Coward Aug 11 '15 at 16:07
  • I guess not. This is going to be hosted in a xen-virtualization environment. – zwirbeltier Aug 11 '15 at 16:12
  • By "working with his/her data" do you mean that the user is sending requests to the server to process the data without the user ever actually seeing it or will the user be able to actually read the data as well? Given the latter, a MITM is very possible when the data is sent between the user and server. This was not part of your question but I figured I'd mention it. – Alex Aug 11 '15 at 20:56
  • 1
    Why not encrypt user data client-side via AES-256 with their cleartext password? For instance, when they enter in sensitive information, ask them to verify their password. If the password they entered matches their registration password, derive an AES-256 key from the cleartext password in Javascript, then encrypt the information before passing it onto the server-side aspect of things. When they need to access sensitive information, make them enter their password, check the password, derive a key, and decrypt data. Just make sure you use a strong password hashing algorithm such as bcrypt. – Sakamaki Izayoi Aug 12 '15 at 2:15
  • One of the important points of the application is server-side data processing that can't be moved to the client-side. So one of the conditions is that the server must have access to the unencrypted data during a user session. – zwirbeltier Aug 12 '15 at 5:41
6

Question 1

Question 1: Are there any obvious security flaws in that scheme (except that the attacker can access the data of all logged-in users)?

Proposed scheme:

Registration

  1. The user digests a password key P from the plain-text password p using SHA 256
  2. The user sends this key over a secure connection to the server
  3. The server generates a random key k which is used to encrypt data before it's stored
  4. The server encrypts k with P and stores it for later use

Authentication

  1. The user digests the password key P and sends it to the server
  2. The server decrypts k and stores it in memory

Security concerns

Password derivation

The above scheme suggests p to be hashed. This alone does not ensure "perfect" forward safety since a hash value can be looked up in a Rainbow Table to retrieve the user's plain-text password. Attackers can also use one cracked hash value to determine other users' passwords due to the lack of salts. These concerns are mostly privacy related ones since they only cover what could happen when the database has been accessible to attackers.

To conclude the above mentioned vulnerabilities:

  • Rainbow Table lookup
  • Brute Forcing
  • Identical hash values

What to do to address the issue

Registration

  1. The user generates a random salt S of sufficient size
  2. The user derives a password key P from the plain-text password p and S using a strong key derivation function such as PBKDF2
  3. The user sends this key along with S over a secure connection to the server
  4. The server stores S
  5. The server generates a random key k which is used to encrypt data before it's stored
  6. The server encrypts k with P and stores it for later use

Note: The salt should be unique to the user and the key derivation function should run for as long as possible (calibrate it to run for about a second).

Question 2

Question 2: To what point does this way of doing the password recovery reduce the effect of the encryption? (Is it still worth doing?)

Proposed scheme:

Registration

  1. The user's email is sent alongside P
  2. The server encrypts the user's email and P with the recovery server's public key and stores it

Recovery

Disregarding the actual "user selects new password" part ( identical to the registration process )

  1. Server sends the user's email and password key ( which are both encrypted with the recovery server's public key ) to the recovery server
  2. The recovery server decrypts the requested data and sends it back to the main server
  3. The main server is able to encrypt the data with the new password key

Security concerns

There is always a physical threat when using "master keys". It is good that you've understood that it is vital to have it on a seperate system on a seperate server so that if one system is compromised - actions can be taken to ensure that the stored data remains safe.

Private key storage is to broad to answer here but I'll try to give you some resources to further look into it yourself.

The security of the connection between the both servers are extremely important. They must be able to trust each other even when there's a middle man. HTTPS is not enough and multi-layer security is one step to ensure that users' data won't get compromised. An application layer of security can do good in this case with session keys and RSA on top of SSL/TLS.

Then there's the practical...

Trusted administrators of the recovery system can obtain the private key and use it for different mailicious causes.

Encrypting larger amounts of data with RSA isn't feasible today. It will take way too long time to ever be of use. The standard solution today is to generate a random encryption key, encrypt the payload with the key and the key itself with the recipient's public key. Then both the payload and the encrypted key is sent to the server which then decrypts the encryption key with it's private key and the payload with the encryption key.

Anyone with access to the user's email should not be able recover a user's password. You mentioned "a 2-factor authentication service" which will help ensure that only the user can change the password.

To conclude:

Every time the data is sent over a network it is exposed to vulnerabilities. The fewer time it crosses a network - less likely a MITM will be encountered. This can be solved using tokenization which replaces sensitive data with a random string that only your servers can relate to data.

Large amounts of data cannot be sufficinetly encrypted using RSA as of now.

What to do to address the issue

Recovery

Disregarding the actual "user selects new password" part ( identical to the registration process )

  1. The server generates a random encryption key to encrypt the payload with
  2. The key is encrypted with the recovery server's public key
  3. The server encrypts the user's email and password key ( which are both encrypted with the recovery server's public key ) with the "payload key" and sends it and the encrypted payload key to the recovery server
  4. The recovery server decrypts the payload key using it's private key and then decrypts the requested payload using the received payload key and then decrypts the data with it's private key
  5. The same communication step with multi-layer encryption is used to send the data back to the main server.
  6. The main server is able to encrypt the data with the new password key and store it again
  • I proposed hashing because derived key is not stored in any way. It is only used to encrypt/decrypt the (randomly generated) user-key that is used for data encryption. Of course the database record contains the hashed (slow, strong, salted) password to verify the password on login. I've left that out as the question doesn't deal with the user authentication process. – zwirbeltier Aug 12 '15 at 16:46
  • @zwirbeltier Ah, I see. I'll try to correct for that – Alex Aug 12 '15 at 16:47
  • @zwirbeltier There is still the possibility of identical hash values though. If an attacker is able to come up with one password hash - it can decrypt all the user keys that were encrypted with the same password. Some sort of salt is still needed. (PKDF2 won't do much performance difference for rarely visiting users but can address concerns like this). This mostly concerns a compromised database – Alex Aug 12 '15 at 16:54
  • I really like your take on Q2. So perhaps I would send RSA.enc(master_public, random_key)+AES.enc(random_key, user_key+email)+key_from_pw(new_password) to the password-reset-server which then answers with a RSA.sign(master_private, AES.enc(key_from_pw(new_password), user_key)). - So the password-reset-server never sees the actual user data (encrypted or not). BTW: is there some common notation for stuff like that? – zwirbeltier Aug 12 '15 at 16:57
  • Users with the same password having the same key encryption key is a valid concern. That would already be mitigated by using a per-user-salted hash though. (I doesn't need to be slow for that.) – zwirbeltier Aug 12 '15 at 16:59
1

Sorry to rain on everyone's parade but this is really bad idea. (Nice thread btw! but right answers to wrong question.

You have created a complex DIY crytography scheme which is a bad idea in general since your implementation will introduce more vulnerabilities then you have today.

Take a step back and do a threat analysis.

  1. Start with assets - how sensitive is the data.
  2. Think about vulnerabilities - what are the attack vectors?
  3. Then think about threats AND THEN and only then
  4. Think about security countermeasures

you should never start with designing and implementing security countermeasures before you do the threat analysis.

Now that I've finished lecturing - lets' think about some typical threat scenarios.

Threat scenario 1: An attacker gains root access after having guessed your SSH password and elevates privileges by guessing the password of a user with sudo privileges. Your scheme will not be effective against an elevation of privilege attack.

Threat scenario 2: SQL injection - attacker succeeds in gaining admin access to your SQL server - the right countermeasure will be using stored procedures and sanitizing your input to make sure you mitigate SQL injection vulnerabilities.

Threat scenario 3: Abuse of SOP (separation of privilege) by users - i.e users may attempt to view/URL hack data of other users. This is a typical threat scenario in sensitive medical data. In this case (and I don't know what kind of Web app framework you are using) the appropriate security countermeasure is RBAC - role based authentication - not user-centric encryption. Typically in MVC frameworks like RoR and CakePHP or Dot Net - RBAC is baked into the framework so you don't have to invent the wheel.

Threat scenario #4 - someone steals your server.

You said you're developing a Web application. I assume you're using a cloud server. Hopefully on a good cloud provider like Amazon or Rackspace or Azure.

Encrypting data on a server is only an effective security countermeasure if someone physically steals the disk or the server.

The probability of someone stealing your VM on Amazon, RS or Azure is ... correct...zero.

There is at times - compliance requirements for data at rest encryption - this almost always relates to removable/mobile devices but if you must there are TDE (transparent data encryption capabilities) in modern SQL servers - MS SQL and PG for example

HTH!

  • Hi, first thanks for your thoughts! But … 1. You are wrongly presuming that this countermeasure is not the result of a risk analysis. 2. You also assume that this is the main/only countermeasure taken 3. You name one possible scenario where this encryption scheme would be useful yourself: A hacker gaining root-access to the server. (With encryption he/she is unable to decipher the sensitive data). -- Later you say that this is only useful in case the server is stolen. – zwirbeltier Sep 1 '15 at 20:01
  • Great thread! To clarify - whole disk encryption is good for mitigating theft of the server/disk but doesn't mitigate elevation of privilege since a root user will be able to access the logical volume. OTOH - your countermeasure is indeed effective for mitigating root kit threats and SQL injection attacks where the attacker manages to gain admin access to the DB server. My main concern here is that it's complex and that your implementation will require extensive testing and validation and god knows vulnerabilities neither you nor I can think of right now. – Danny Lieberman Sep 2 '15 at 6:49
  • 1
    Database-level encryption or volume encryption is not planned for exactly those reasons that you state above: theft of the hardware is unlikely with a virtual server. Bugs in the application or server setup are much more likely - that's the reason for this scheme. We are planning to do security audits on this scheme and it's implementation. Asking here was only a first check for obvious flaws. Thanks again for taking the time to answer. – zwirbeltier Sep 2 '15 at 6:54
  • Thank you for a stimulating a great discussion. One tries to estimate cost vs. effectiveness of security countermeasures in light of asset value and operational environment, which obviously I don't know in your case! – Danny Lieberman Sep 2 '15 at 7:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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