You heard me. You know how weak your user’s passwords likely are. You know your users are almost certainly sharing their passwords with multiple sites. You know that a compromise of your database could lead to significant damage coming to them. You know this because it happens all the time, all over the web.
You have a duty to protect the security and privacy of your userbase. They’ve entrusted you with their data, and it is on you to keep it safe. So why aren’t you doing everything possible to accomplish that task? For this blog, we are going to talk exclusively about password storage.
If you ask just about any security professional in the world how best to store a password, you’re liable to hear something about using a cryptographically secure hashing function “with a salt.” Some will go so far as to mention algorithms like Bcrypt or Scrypt. Very few will make any mention to how password policy plays a significant part in ensuring the security of any stored values.
But almost none of them, will even mention the word “pepper.” Now I suspect this isn’t malicious, (obviously). I think even most security professionals simply aren’t informed enough to know or act with regard to this concept.
So today we’re gonna work on that…
What is a pepper?
You’ve probably heard of “salting” a password hash. You probably know that this means to take a random value (the “salt”) and append it to the plaintext during the hashing process, like so: doHash(password + salt). This salt value is then stored next to the password hash, so that it can be used again when the user authenticates. It is not a secret… It doesn’t have to be. A salt is useful because it means that even common passwords will have a unique hash value given that their salt is unique.
But what is a “pepper”?
To “pepper” a hash is to append another value to it like so doHash(password + salt + pepper). But in this case, the pepper is considered to be a sort of pseudo-secret… meaning that it is not stored alongside the hash. The idea here is that if an attacker manages to compromise the stored hashes, they will be useless to him unless he also compromises the entire application (and/or the stored location of the pepper value > which is accessible from the application).
The application knows where the pepper is, and it can retrieve that value when it goes to perform a hashing operation. But by storing it in a different location far away from the hash values, it massively increases the security of all of your stored passwords.
Imagine this scenario…
All you have to do is use a pepper
You store your password hashes inside of a database.. you salt properly, and you make sure to use a cryptographically secure hashing algorithm like SHA256. You even have a strong enough password policy that you assume it will be difficult for an adversary to brute force any of the values contained in any of the hashes.
But one day an intern ads a line of code into a dev box connecting to your database, accessible from the web. This line of code is vulnerable to SQL injection, and someone dumps your database…
It’s very likely that a lot of your user’s passwords are going to be cracked. It’s very likely that a lot of your users are going to suffer real damage from this breach. It’s very likely that at least some of them will have radically different lives when the dust settles.
You want to stop that? All you have to do is use a pepper. With a pepper stored somewhere other than the database… the SQL injection attack would reveal password hashes that would be unusable to the adversary. In order to be able to brute force any of them, he would first need to find a new attack to gain full control over your application in order to dump the pepper value which is (assumedly) stored in a text file somewhere inaccessible from the web.
The use of peppers may be considered to be part of a full “Defense in Depth” strategy as a bulwark/mitigation for SQL injection attacks targeting database resident password hashes; in much the same way that a strong Content-Security-Policy may protect against injection attacks. Or HSTS against TLS downgrades and insecure cookies.
On the use of block ciphers
Just a note, block ciphers with a secret key stored in the same manner as the pepper may be used to protect more than just passwords, with arguably a higher level of security given that they can be cycled out without user interaction. If you’re gonna chose between encrypting the data in your database, and using a pepper with your password hashes, I would urge you to go for both.
Though of the two full data encryption is easily more effective… We’re not covering that in this article as the “solution” for one simple reason. Peppering is something you can add to your codebase with minimal changes, today…
I hope you will.