5 ms·
I'm not sure why implementing pepper (alongside, or even instead of, salt) is so rare. It's arguably much easier to implement than salt, and protects against bo
by dvt 6y ago
I'm not sure why implementing pepper (alongside, or even instead of, salt) is so rare. It's arguably much easier to implement than salt, and protects against both attacks described here.
The only caveat is that your database isn't coupled tightly with your application code, so your pepper remains secret even if your DB is breached (which is usually the case).
- edflsafoiewq 6y ago> It's arguably much easier to implement than salt Salting is easier since it can be completely wrapped up in the key derivation function. The programmer doesn't have to know anything about it, they just use generate_key(passwd) and check_password(passwd, key).
- zemnmez 6y agoyou really shouldn't be implementing your password hashing algorithm from basic crypto primitives. s/bcrypt works right out of the box with no config.
- mberning 6y agoI have wondered the same thing. Make it a piece of data that comes in from the environment or a secrets manager. It’s not bulletproof, but if done correctly seems like it makes the whole hashing scheme a little better.
- lookingfj 6y agoIf you are doing this isn't it pretty much the same as encrypting it with a key?
- liambuchanan 6y agoencryption is non-deterministic
- iso8859-1 6y agoif that was true, this article wouldn't exist: https://en.wikipedia.org/wiki/Deterministic_encryption https://en.wikipedia.org/wiki/Deterministic_encryption
- quesera 6y agoSome encryption algorithms are (effectively, but not literally) non-deterministic, e.g.: DUKPT, RSA-OAEP Most encryption algorithms are deterministic, and most password authentication schemes depend on that fact.
- srtjstjsj 6y agoPasswords aren't encrypted, so why would deterministic encryption matter?
- quesera 6y agoErr, yes, good point. And if I had read the article first, I would have had the proper context of technical specificity loaded before commenting. Nevertheless, most encryption algorithms are deterministic. :)
- dec0dedab0de 6y agopepper instead of salt is a bad idea because if your pepper is leaked the attacker can brute force all of your passwords at once. The main argument I've heard against pepper is because people are afraid of losing the pepper. It either needs to be directly in your code which is easier to leak, or out of band which is easier to lose. edit: Does anyone else want to goto waffle house whenever they talk about salting and peppering their hash? Too bad the closest one is an hour away.
- dvt 6y ago> pepper instead of salt is a bad idea because if your pepper is leaked the attacker can brute force all of your passwords at once. This isn't true, you could simply do encrypted_pw = md5(pepper + md5(password)) or whatever. Edit: Getting a bunch of comments on this, just want to clarify that I used md5 purely to illustrate a one-way hashing function. In actual practice, you'd use something else (HMAC with SHA256 most likely).
- dec0dedab0de 6y agoIf that gets leaked the attacker could brute force that, and match the results to your entire list of hashes. If they're salted, they would still have to brute force each password individually.
- dvt 6y agoTotally agree with this, hence the caveat that the code doesn't get leaked/compromised :)
- marcinzm 6y agoHow does that help? They can iterate through possible passwords and generate md5(pepper + md5(password)) just as easily as md5(pepper+password). The point is that they can iterate ONCE and match against all passwords in the DB. With salt they have to iterate for each row in the DB which is much more time consuming.
- taywrobel 6y ago
- skissane 6y ago> The only caveat is that your database isn't coupled tightly with your application code, so your pepper remains secret even if your DB is breached (which is usually the case). There are many attack scenarios in which storing a secret separate from the DB doesn't get you much at all. Suppose an attacker finds an RCE vulnerability in the application – then they can slurp up the contents of the DB, but they can read the pepper from the configuration too. Suppose they just have a SQL injection – they can't directly get the pepper from a SQL injection, assuming it is being stored somewhere outside the database. But, it may help them do it indirectly – for example, they could UPDATE their account to have admin privilege, and then access admin-only features of the application which may end up revealing the pepper. I've seen many apps which have admin-only screens to run arbitrary scripts, view configuration files or environment variables, install plugins, etc – those kind of features are helpful in supporting the application, but can be used to turn a SQL injection into more complete control over it
- agustif 6y agoAdmin tools should probably be IP whitelisted instead than open to the world if admins are few?
- charwalker 6y agoIs that not the default? Err on the side of better security?
- dathinab 6y agoYes, furthermore (db) admin login should preferable be done over a different SQL user so that a normal usages SQL injection can never be used to update anyone to have any admin rights. But then just giving the default user admin rights can make many (not so good but widely used) deployment tools and methodologies and similar much easier to use so you see it quite often. I have seen it a few times. Default db user being a db admin because the ad-hoc written deployment script during initial development was never updated and security didn't matter back during per-release bootstrapping. ;=(
- hn_throwaway_99 6y agoA pepper is essentially a secret encryption key (it's a long secret string that's added to the password and the salt to ensure more entropy). With cloud key management services (e.g. both AWS and GCP have a KMS), I think it's more beneficial to just encrypt the hash before putting it in your database. Process looks like this: Upon password creation: 1. Generate hash as hash of password + salt. 2. Encrypt the hash with a public key from KMS (you can store the public key in your server code). 3. In your database store the encrypted hash, the salt, plus some "key ID" that identifies which KMS public key you used (this is so you can rotate keys later). Upon user login to verify the password: 1. Retrieve the user's encrypted password hash, salt and KMS key ID from the database. 2. Make a call to KMS to decrypt the hash (KMS internally stores the corresponding private key but never lets you access it). 3. Then hash the password the user entered + salt and compare it to the decrypted hash to see if there is a match. Benefits of this are: 1. If an attacker steals your database, they can't decrypt any of the passwords or the password hashes. 2. KMS never exposes the private key of the async key pair, so you know this won't get exposed either. The only way to decrypt something is to make an API call to KMS. 3. Thus, the only valid attack really is if the attacker is able to gain the same access privileges as your server. But even then they still need to call KMS one-at-a-time to decrypt hashes, and all of those KMS calls are logged in an audit trail, so it should be much easier to see if you have anomalous calls to KMS. There is a huge benefit here in that it is impossible to do bulk decryption without a giant audit trail.
- t0astbread 6y agoBookmarking this. Additionally I assume you could also limit access to KMS so that only your servers can issue requests.
- hn_throwaway_99 6y agoYep. Not sure the details of AWS, but in GCP access to KMS APIs and specific keys is controlled by IAM, and you can set "conditions" on IAM policies to restrict access by things like IP of the request: https://cloud.google.com/iam/docs/conditions-overview https://cloud.google.com/iam/docs/conditions-overview