3

In my app I'm using Facebook login and creating a local user in my DB after retrieving the data.

When saving the Facebook ID in the DB I need to hash it, as I don't want the ID to be in clear text if someone gets my DB data (I want to prevent, as much as possible, a way to connect the data to an actual person on Facebook).

The problem of course is, that I can't use random salt with my hash, as I won´t have a way to search my DB later on, when the user logs in.

So I thought about a few solutions, though none of them, in my opinion, is good enough:

  1. Use same server salt for all hashes.

  2. Encrypt the Facebook user_id instead of hashing.

  3. Create dynamic salt as a function of the user_id - something like:

Hash(Hash(user_id) + user_id)

Is there a way to truly secure this scenario?

vandus
  • 103
  • 2
Udi Idan
  • 133
  • 1
  • 9

2 Answers2

2

You're missing a threat model

I see two obvious threat, both involving being able to query your database. There surely are others (suggestions welcome):

  • A - An attacker stole your DB (and server salt) and wants to infer the Facebook IDs of all your users
  • B - An attacker knows the Facebook information of a specific user and wants to figure out if they exist in your DB (without breaking all its entries)
  • C - An attacker with exactly the same capabilities can also change the code running on your server, adding information stealers that will report the IDs/passwords of users as they log in over time

Let's now look into your proposals

  1. Use same server salt for all hashes.

This is still necessary to avoid pre-made rainbow tables, but indeed will only slow down any attack carried out for A or B. Make sure to combine with a slow hashing function to further increase the cost of finding your hashed IDs for A.

  1. Encrypt the Facebook user_id instead of hashing.

How do you decrypt your IDs when a user logs in? Surely the decryption key is stored somewhere. You could store the encryption/decryption key on a separate physical device, so that decryption attempts must take place on the server rather than truly offline, since the key can't be taken. There might also be systems that can alert you when a threshold of decryption requests is reached but this is not my area, I don't know if it exists (just note you can't rely on your server to do that because of the threat model; your server is fallen).

You could also store the salt in that device, and then in both cases the security is a factor of how long it takes an attacker to encrypt/hash a known user ID with all possible keys/salts. I am not a crypto expert at all so I can't give any orders of magnitude on what's best to do but intuitively a crypto scheme with a large key is better (also probably more computationally expensive).

  1. Create dynamic salt as a function of the user_id - something like:

    Hash(Hash(user_id) + user_id)

Well, this is rather useless. If you want to complicate an attack for the A threat, then you need to ensure that the additional information is independent from the ID you hash. For instance, an email address or date of birth will vary from user to user, effectively increasing the input search space of your attacker. The B threat is completely unaffected since all the Facebook data is already available to your attacker.

Here it's hard to do something against B... If they know your hashing algorithm and can check if a specific hash is in your DB you can't do much. But again this is more likely the same capabilities as threat C, which is even more serious. Of course good hashing practice is important to slow down an offline bruteforce attack but you also need to consider the other issues you'll face in such a scenario. You should find out how to detect attacks and alert your customers that they might be phished or spammed because of a breach on your service (as a motivated attack will eventually have retrieved all the user IDs).

Steve Dodier-Lazaro
  • 6,828
  • 29
  • 45
0

I don't really understand why you can't search in the database once the user has logged in. Can't you save the username as part of the session? (or the salt if is that what you need).

Of course this will be a bit PITA since you have to hash the username every time you want to do a query. But to avoid this (and if you are really so into hashing the username), why don't you use the username hash itself as part of the session, or better, why don't you add an extra numerical user id to the same user table and use that number to make the queries in your database?

Your dynamic salt hashing suggestion sounds a lot like rolling your own.

As a security note, I don't believe hashing usernames is going to give you a great security, I don't even know if the salt is going to add you extra security since I believe all the usernames should be the different... Also, usually, usernames are easy to guess so I believe rainbow tables will be very helpful and so you add little to none security.

kiBytes
  • 3,470
  • 16
  • 26
  • Lets say user 001 Logins for the first time and I create a record for him, hashing 001 with random salt, and store the salt in the DB next to the hash. Now the user logs in again, I know he's user 001, but how can I know the salt I've used to hash him originally to query the DB? – Udi Idan Feb 25 '14 at 09:09
  • I am sure I am missing something but you have said: "001 with random salt, and store the salt in the DB next to the has", well so you have the salt stored, don't you? Just use it =) (or you are prehashing the username and THEN sending it?) Then that is not the way. – kiBytes Feb 25 '14 at 09:31
  • 1
    But each user has different salt. I would need to try hashing with each salt to find the user, or am I missing something? :) – Udi Idan Feb 25 '14 at 09:35
  • That's the big problem on hashing the username... You will have to test EVERY row in your DB. Why don't you try to cypher the rest of the data instead? (maybe with the user password or something). I believe you are on the wrong path in securing the user info. – kiBytes Feb 25 '14 at 09:37
  • I do intend to encrypt the data, I just want it to be as secure as possible. – Udi Idan Feb 25 '14 at 09:40
  • Then, be sure your data is properly encrypted instead of adding this username hashing part which I believe it is a bit nonsense and it is going to drive you crazy when trying to data mine your very own application. If you really want a secure application be sure to hire a security consultant =) – kiBytes Feb 25 '14 at 09:42
  • Actually my intention was to make data mining as hard as possible. If it would be hard for me, it would me nuch harder for an attacker, so I assume. – Udi Idan Feb 25 '14 at 09:44