0

We used MD5 with salt to hash user passwords and store in database. BUT the salt is hard coded in code.

So, any developer who has access to code and database, can use brute force algorithm to match/recreate the hash.

Can someone help me what are best practices to keep salt away, even from developers. Let's just say, I want to restrict access to salt just to me(application owner)

I was thinking in terms of U2F or HSM, but I don't see how they fit here.

I don't want to use random/different salt for each user, because it doesn't solve my problem. I still have to keep those salt in database, that developers can access.

Note: I want to protect passwords from internal users/developers, who developed the application

Thanks

sorabzone
  • 797
  • 5
  • 8
  • Does this answer your question? [The necessity of hiding the salt for a hash](https://stackoverflow.com/questions/213380/the-necessity-of-hiding-the-salt-for-a-hash) – Klaus Gütter Jul 25 '20 at 03:07
  • @KlausGütter this thread caters similar problem, but no one provided any solution to that. I have a solution in my mind but I am looking for best practices, experts are using for it. It is very normal and genuine problem but seems no one caters it. – sorabzone Jul 25 '20 at 03:12
  • My idea is to create and host my own password service. Developers call this password service to get hash for a password. So CreateUser/SetPassword APi calls --> PasswordService to get the hash. And service code is only private to me. – sorabzone Jul 25 '20 at 03:17
  • Why do you want to hide the salt at all? The purpose of the salt is to protect against dictionary attacks (rainbow tables), and this purpose is reached whether or not the salt is hidden. If you are concerned about the weak MD5 algorithm, you should choose a better hash. – Klaus Gütter Jul 25 '20 at 03:18
  • @KlausGütter Recently it happened with a company i know. The lead engineer resigned and he has database and code backup with him. He used brute force algorithm to regenerate and match password hash, because the salt value was hardcoded in code. That company also track the device and IPs against each login, they observed unusual behavior and login from many devices. I can change the algorithm, but I still need to protect the salt from developers. – sorabzone Jul 25 '20 at 03:20
  • 1
    Imo your biggest problem is the hardcoded salt. The whole idea of salt is to have a unique value for each user so once a hacker knows the salt values he has to brute force per user instead of doing a single bruteforce for the entire database. After that your worry is that the cost of brute forcing a single user might still be too cheap but you need to change other things instead of the salt to be stronger against that –  Jul 25 '20 at 05:07
  • @Knoop You don't get it. I am not talking about external hacker. The attacker is application developer working on this application he already has hashed password and salt from database. Even if you use unique salt for each user, he still have access to it. he can go home and run the brute force algorithm. I want to secure or restrict access to salt. – sorabzone Jul 25 '20 at 05:48
  • The whole point of salt is to minimize risk in case anybody gets access to the database. Doesn't matter if that's an internal developer or an external hacker. And with the way it's implemented right now anyone that gets a copy of your database can create a single rainbow table for the entire database. Also in the scenario given above the lead engineer falls under the definition of hacker (I never mentioned external, you added that specification on your own) –  Jul 25 '20 at 05:58
  • Correct!! For external threats I have many things implemented. But for internal attack, I need to secure salt. – sorabzone Jul 25 '20 at 07:36
  • Realistically, you need a better hashing algo. All you're doing with your approach now is hoping for "security by obscurity" - the fact that only you knows the salt, effectively. You're proposing to take the existing hash and salt etc, out of the "known by all devs" codebase and make another hashing server that only you knows the code to; that's fine and secure enough while only you knows it etc but it introduces a single point of failure, and doesn't solve the problem that someone is out there with the ability to brute all the existing users – Caius Jard Jul 25 '20 at 08:19
  • Even if I switch to SHA256/512 or any other algo, I still need the salt and keep it secure. Single point of failure is a basic problem, can be easily handled. Thanks for your input. – sorabzone Jul 25 '20 at 08:27
  • 2
    SHA aren't really any better than MD5 because they still run quickly and are hence viable to brute. Yes, you need a salt, but securing it is not the thing that brings the true security, and the single point of failure is not necessarily the hashing server, but *you* - you get hit by a bus and the access to the salt dies with you. I'm saying you need to de-incentivise brute forcing by making it take a looooong time.. a hashing algorithm that can only do X hashes per second for example, X being a factor of how many users log in every second. A slow algo's salt can be known to all – Caius Jard Jul 25 '20 at 08:33
  • A salt is not a secret value, and it must be unique per user. A single salt for a whole db is useless. In addition, you may *also* include a value commonly called pepper, which is used like a salt but is kept secret on the server side and commonly hard-coded into your software. It is not used in place of the per user salt, it is used together with the per user salt. The point of pepper is to force the attacker to also obtain your code. Just grabbing the password database would not be enough. If you are using a single salt you're doing it wrong. – President James K. Polk Jul 26 '20 at 15:20

2 Answers2

1

The problem you've got with your current idea of encrypting the salt is merely "kicking the can further down the road" In order to be usable the salt will need to be decrypted, which means the code will have to know how to do the decrypting, when means the developers will know how the code does the decrypting and its parameters

You could, of course, keep the decryption key in a secure string in memory only, never save it to disk and create an interface that lets the company CEO paste the key in (over an encrypted connection) from a USB he carries on a chain around his neck, that has a thumbprint lock.. etc.. and he needs to do that every time the server is restarted..

As per the comments, having a single salt could easily be switched out for a per-user salt, but your rogue dev probably still knows the users who are worth attacking so it might not help much if there are only a handful of them.

You really need to be looking at a hash algo that is a lot slower (devices that do billions of MD5 hashes/sec have existed for a long time), which means that brute forcing the passwords is unviable. There is of course a trade-off with these; they are much more work, computationally, for your server and by deliberately implementing something that is slow and takes a lot of resources you can line yourself up for DOS attacks, that will then need mitigating by separate means.

The immediate solution to your problem, if this is actively happening, is to change all the users' passwords and have them reset them to something else. You can detect if they change them back to what they were before (because the hash of the new will be the same as the hash in the backup table you'll create before you change everything). This has the side effect of letting your users know you've been compromised, but you could window dress that as your "awesome security systems have detected suspicious activity and locked their account for their safety" if you need to avoid revealing you've been compromised. Dealing with the company image fallout of this isn't something I guarantee can be swept under the rug but it's a problem for your marketing department rather than SO..

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • my plan is to create and host password service. Nobody can access to it or source code, except me. ofcourse I have to open socket or http connection for other services to call the GetHashedValue() method. – sorabzone Jul 25 '20 at 08:02
0

The salt has its very own job, to mitigate the usage of rainbow tables when the stored hashes are known to the attacker. What you want to prevent is an entirely different threat, so we should let the salt do its job and use a different solution. See also my tutorial about safely storing passwords. BTW MD5 is not appropriate to store passwords, use a password-hash function like BCrypt, Argon2, PBKDF2 or SCrypt instead.

What you can do is, to encrypt the already calculated hash values with an additional server side key. This en-/decryption can be delegated to a service on another server if necessary (HSM).

Especially if you want to protect from an insider attack, you should switch to one of the mentioned hash algorithms with a unique salt for each password, they are possibly your only protection from a successful brute-force attack, MD5 is way too fast and can be calculated at a speed of 100 Giga MD5/sec.

martinstoeckli
  • 23,430
  • 6
  • 56
  • 87