If you’re not peppering your passwords, you are irresponsible.

Actual hacker

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.

About the author

I do a lot of stuff. I'm a decent hacker. I jump out of airplanes a lot. Done some firefighting and stuff. Philosophy all the time, make music, acting in awesome indie films. Just, a lot of stuff.

Comments

  1. Wouldn’t an attacker only have to manage to bruteforce 2 of the hashes in order to discover this pepper, which would just be the text that is common between them?

    1. Not in any case in which peppering is implemented properly.

      If a hash is constructed as follows: h_n = doHash(password + salt + pepper)

      We assume the attacker is able to generate an account on the service and as such may know for a given hash h_0 the password and salt values (as the salt is stored in the database). Say the attacker manages to dump the database, and now wants to brute force all of the stored passwords. They have their hash h_0 for which they know the salt and password. In order to discover the pepper value, they would have to brute force the pepper value…

      As long as the pepper value is long and random, this will never happen. And since we’re just storing the pepper somewhere, and accessing it programmatically, this is very easy to accomplish.

      Does that make sense?

  2. Is it really necessary to do both ‘salt and pebber’? Does doHash(password + pebber) not provide the same level of security as doHash(password + salt + pebber)? Thanks in advance.

    1. Hey, thank you for your comment. Adding a pepper to your password hashing process does greatly increase the security of your stored hashes. The reason for this is because the pseudo-secret pepper value is stored somewhere other than the database, an attacker who dump just the database cannot do anything with the hashes he captures until he also finds where the pepper is.

      The big example of this is that maybe there is a SQL injection vulnerability in your website. If you don’t pepper, an attacker who uses the SQLi to dump your database will be able to attack the hashes. If you pepper those hashes, when the attacker dumps them, he’s not able to learn what the plaintext’s are unless he finds another vulnerability that helps him steal the pepper too!

    2. No, because the pepper is constant, so without a unique salt per account, the same password would hash to the same value.

      An attacker could then spot repeated passwords in the database, which are likely to be weak.

  3. I think you misunderstood my question. I was not wondering about the effectiveness of ‘peppering’. I was asking about why would you still salt, when you pebber.

    1. Salting passwords goal is to foil rainbow tables. If there is only a fixed “pepper” and no salt, then you are still vulnerable to rainbow tables attacks.

    2. With only a pepper, users with the same password would have the same hash. This could potentially leak information if the database was breached.

  4. Anders, what is not made explicit in the article is that there is only a single pepper used for all passwords. If only a pepper is used instead of both a salt and pepper, it would be nearly the same as if the same salt is used for all passwords.

  5. The traditional definition of the difference between salt and pepper is that the former is unique on a per-user basis, and the latter is shared between all users in the database. A careful reading of your article implies this, but doesn’t make it clear; making it clear would probably resolve questions like Anders’.

Leave a Reply to Matt Palmer Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.