16 ms·
Peppering (Password Storage)
- noodlesUK 6y agoThis is a very good idea if you know you will be on a platform that supports long-lived secrets like k8s or a provider like AWS. It means a db dump is way less dangerous in terms of password reuse, assuming the compromise was something like SQLi.
- sroussey 6y agoYeah, but the reality is somewhat more complicated when you operationalize. The pepperId can be the same for everything, or can be per shard, or just chunked across large sets of records. And pepperId = 1 can have the value of the empty string, which is what all non-peppered have. Now it’s easy to increment the pepperId for new records and have a real value stored elsewhere. But... bring it to the ultimate conclusion and you essentially are splitting the salt between local and remote storage.
- GoblinSlayer 6y agoThe salt is public by design, it's not intended to be secret, only unique. For pepper secrecy is essential.
- ballenf 6y agoIt should have been called "spice" or "herb". Instead of the name of a single, known raw ingredient.
- raesene9 6y agoif you're on k8s, and you get access to secret objects via the Kubernetes API, you're getting the secrets in the clear, no hashing or encryption. If you get it via an etcd database file from disk or via direct access to the etcd API, then the best approach is usually to have setup the `--encryption-provider-config` option on the API server so that secrets are encrypted with a secret not present on the etcd server.
- willcipriano 6y agoI'm a big fan of peppering. It strikes me as a defense in depth move. Say a programmer on your team accidentally pushes code that makes your salt a static value for all users going forward, the pepper might protect user passwords in that case.
- georgyo 6y agoYour pepper is always static, and your salt becomes static. Wouldn't that essentially be peppered even without the pepper? I don't see any value of a pepper. It doesn't actually add any protection.
- willcipriano 6y agoNo, because the static salt will be stored in the database alongside the passwords. The pepper would be compiled and live in the application layer. The value is minimal but so is the cost.
- Sherl 6y agoIf it's static salt, it breaks the use of salt. Salt was designed such that a rainbow table cannot crack two similar passwords based on hash, exactly what a static salt would facilitate.
- stouset 6y agoIf not stored in the database, it ensures that a database dump alone isn’t enough to recover even a single password. It certainly doesn’t have the level of impact that salting passwords or using a cpu-hard and memory-hard hash does, but it’s certainly something. Modern password hashes like argon2 include this feature natively.
- tialaramex 6y ago> Say a programmer on your team accidentally pushes code that makes your salt a static value for all users going forward This should fail an obvious unit test for the password handling code. The obvious unit tests for this component include a check that minting two password hashes for the same password gives different results.
- stouset 6y agoI don’t like the OWASP recommendation here to concatenate the pepper and password before having. Generally speaking, you should not be smashing unlike things together into a single cryptographic input. If you find yourself doing this sort of thing, it’s worth taking a step back and seeing if there’s another primitive that better meets your needs. It’s probably fine to do it this way for anything approaching a reasonable password hashing function, but it does leave a bad taste in one’s mouth. Likewise, I’m not a fan of encrypting password hashes since there’s no need to have a two-way function for password verification. Again, there’s probably no exploit. But over and over again we’ve seen ways where attackers have been able to exploit systems where a primitive was used for a subtly different problem than the one it was designed for. Much better: HMAC the password with the key before running it through the hash.
- except 6y agoArgon2 supports peppering/secret parameter where it does a HMAC internally.
- stouset 6y agoYep. When at all possible, use cryptographic tools that natively support the features you want rather than trying to bolt them on top yourself.
- ascar 6y agoThe article directly proposes an alternative that "avoids some of the issues" with adding the pepper before hashing: > An alternative approach is to hash the passwords as usual and then encrypt the hashes with a symmetrical encryption key before storing them in the database, with the key acting as the pepper. This avoids some of the issues with the traditional approach to peppering, and it allows for much easier rotation of the pepper if it is believed to be compromised. It sounds to me that this is the actual recommendation and the other method is more for explaining the traditional approach. Also the two-way function has a clearly stated benefit in this case.
- viraptor 6y ago> smashing unlike things together into a single cryptographic input What do you mean by "unlike" in this case? You're storing part of the password locally and getting part of the password from the user. If you don't trust your hashing function enough to do that, why do you trust it for the password in the first place? Or specifically - are you worried about common prefixes in this case, or something else?
- GoblinSlayer 6y agoTo prevent hash reuse you can hash the password with a constant per site salt, e.g. bcrypt(sha256("news.ycombinator.com",password))
- willcipriano 6y agoThat isn't a salt. Salts are per user, high entropy random strings.
- rocqua 6y agoIndeed it is not a salt, but it is not what OP claimed. Instead, I think OP was providing a good solution to the following problem stated in the article about using a hash to overcome password length limitations: If an attacker is able to obtain password hashes from two different sources, one of which is storing passwords with bcrypt(sha256($password)) and the other of which is storing them as plain sha256($password), and attacker can use uncracked SHA-256 hashes from the second site as candidate passwords to try and crack the hashes from the first (more secure) site. If passwords are re-used between the two sites, this can effectively allow the attacker to strip off the Bcrypt layer, and to crack the much easier SHA-256 passwords. OPs solution is neither a salt, nor a pepper. It is however, a nice way to prevent the above problem.
- willcipriano 6y agoFair enough, but adding a database column and generating a random string on registration is perhaps a 10 minute job and provides all those benefits plus many more.
- GoblinSlayer 6y agoIf you want a complex solution, you can implement SCRAM https://en.wikipedia.org/wiki/Salted_Challenge_Response_Authentication_Mechanism https://en.wikipedia.org/wiki/Salted_Challenge_Response_Auth...
- coding123 6y ago
- kissgyorgy 6y ago1Password does this. They generate a very long secret key beside your password.
- lawnchair_larry 6y agoFor those who don’t specialize in security, this is not an accepted practice. OWASP is a wiki that anyone with an idea can edit, and there are some bad ones on there.
- Jwarder 6y agoWhat's wrong with it? I don't specialize in security, but I've seen peppers/global-salts in most of the "serious" password storage schemes I've seen. Looks like an easy layer of protection to limit brute forcing hashes from data dumps.
- Ayesh 6y agoThe article is saying it's just an option. Don't bother. If you use a sufficient salt, and a decent hashing algorithm (bcrypt/argon2id), cracking those passwords are impractical for the attacker. If they can do this extremely expensive computational task, an extra pepper reused in all passwords isn't going to add meaningful computational difficulty because the attacker just needs to brute force the secret pepper.
- diarrhea 6y agoBut isn't brute forcing a long pepper very expensive?
- heinrich5991 6y agoBrute-forcing the pepper is computationally infeasible if it was generated with enough entropy. This means the passwords are safe unless both the DB and the pepper is leaked. Even if the user chooses the passowrd "123", the attacker cannot see this with purely the DB. A decent hashing algorithm doesn't help in that way.
- GoblinSlayer 6y agoArgon protects only against naive brute force attack, not against dictionary attack or known passwords.
- twhitmore 6y agoExfiltration of password databases, for offline hash cracking, is a well known attack. Guarding against this by using a pepper is actually quite a good mitigation. It protects in situations where the attacker has obtained the password DB, but has not achieved access to the application secret (the pepper). Breaches of DB are quite a common attack. I prefer the approach where they use the pepper to symmetrically encrypt & decrypt the hash, which potentially allows the pepper to be rotated. Operationally in case of pwd DB being exfiltrated, it's pretty necessary to do something regardless of a strong hash algorithm being used. Pepper, if you can strongly establish it hasn't been breached, can give you a potential option short of resetting everyone's passwords.
- 6y ago
- Puts 6y agoI think the use of stored procedures is underrated. Create a stored procedure to verify the password and only grant permission for the web application-user to run this procedure, nothing more. No one but the database itself needs, or can ever access the hash-column this way. This way you still keep the application separate from the data. I would even argue that we need to get back to the time where there was a DBA handling the data. The dev-ops thinking of mixing application logic and data has introduced a lot of unnecessary security issues.
- GoblinSlayer 6y agoYou can apply several peppers, they are composable, use all you have.
- rlpb 6y agoThis article says: "Writing custom cryptographic code such as a hashing algorithm is really hard and should never be done outside of an academic exercise." I would like to remind readers that the same applies to "salting and hashing". Developers who are not cryptographers should be using an accepted "key derivation function" and not salting or hashing themselves. Examples of KDFs are PBKDF2, bcrypt and scrypt. That's not to dismiss discussion of how KDFs should be implemented. That's presumably very on-topic for HN. But this shouldn't be confused with best practice in using a KDF. If you're implementing a KDF in your application instead of using a pre-built one, you're probably doing it wrong.
- stouset 6y agoLong story short, if you find yourself adding security features (for instance, peppers) to cryptographic tools that don’t accept them as clearly-labeled inputs, talk to a cryptographer first. Concatenating raw inputs is virtually never going to be the solution they’ll give you.
- jwlake 6y agoI don't know if this means I'm old but normal people used to just call this a global salt. The pepper term seems a little cute and not nearly as obvious as "global salt". Though it did get me to click it, which I guess means it market tests well.
- motohagiography 6y agoWas going to say this was the "diversification component," in KDFs. Is someone taking credit for coining pepper, or is it different?
- Waterluvian 6y agoMy wife went on a light hearted rant last night about how us engineers steal all the normal words. “Sometimes it almost sounds like English. Just enough to trick my brain into trying to parse it. Then it hurts.” Now I have to tell her I salt and pepper my passwords.
- gruez 6y agoIt's puzzling why a security resource would use vague terms like "x characters long" to characterize entropy. >The salt should be at least 16 characters long. >The pepper should be at least 32 characters long 16 characters? What characters? digits? alphanumeric? hexadecimal? raw bytes?
- tzs 6y agoA question about upgrading work factors. Let's say you have a secure password hash that includes a work factor, sph(pw, wf) (I'm going to ignore salt to simplify notation). The most widely used ones such as PBKDF2, bcrypt, and scrypt do not include any good way to upgrade an existing hash to a bigger work factor. The way that is usually handled is to flag passwords that are hashed with the smaller work factor and the next time the user logs on you can rehash the password with the new work factor. I don't like that approach. If I'm raising the work factor it is presumably because I decided that the old one is not secure enough. I want to stop using it. I could just invalidate all the old passwords and make everyone go through password recovery, but that is not ideal. Another approach could be to replace all the password hashes that use the old work factor, sph(pw, old_wf), with sph(sph(pw, old_wf), new_wf) and add a flag indicating that they are double hashed. Then update to sph(pw, new_wf) next time the user logs in. I still don't like that. It does solve the problem of having insecure hashes while waiting for people to get around to logging in, but it still requires keeping some extra data around (a flag marking double hashed passwords--or worse if we have to deal with people who have gone more than one work factor upgrade without logging in). What I'd really like is the password hash to be a pair of functions, sph() and sph_cont(), with the following property for integers 0 < wf1 < wf2: sph(pw, wf2) = sph_cont(sph(pw, wf1), wf1, wf2) With that, when I upgrade the work factor I can update all the hashed passwords to the new work factor. So...why aren't the common secure password hashes designed this way? Does it introduce some kind of unavoidable security issue? Just looking at some of them from a computation point of view, not from a security point of view, it seems doable. The general structure is (1) do some setup, (2) do some look wf times, and (3) do some post processing. If the post processing were reversible so that you could get back to the state right after wf iterations then you could do additional iteration to increase the work factor. Is there something that makes it so that the steps between the final iteration and the output must necessarily be irreversible in order for the whole thing to be secure?
- Tostino 6y agoI've had the same question for a few years. Never bothered to ask or research though oh, so I'm glad to see that you asked and I'm eager to see what the consensus is.
- 6y ago
- pontifier 6y agoI was working on a password storage system, and was thinking about how I hate storing user info in the database. I was thinking that you might be able to change the way the username and password are stored on a production database. If you don't store the username, but only store the hash of username and password you're not exposing usernames if the database is compromised. You have to search every row to see if there is a row with a matching hash, but that seems like a small price to pay. Then I wondered if you could take it one step farther, and I think you can! If you store the result of say 15 rounds of hashing in the database to verify things, then you could use the result after only 10 rounds as the basis for an encryption key to decode the rest of that row in the database. Since hashing is a one-way operation, nobody could take the stored hash and go backward 5 rounds to read anything sensitive in that table without the username and password for each row. You'd need another table somewhere else with that data not encrypted that way in order to allow password resets.
- simonebrunozzi 6y ago> One solution to this is to store the ID of the pepper in the database alongside the associated password hashes Wouldn't this expose the pepper to Database attacks (SQL injections, etc), and invalidate the reason for using it in the first place?
- yencabulator 6y agoID of the pepper, not the pepper itself.