11 ms·
I hate to be the negative guy, and they were hashing passwords better than 90% of the sites, but it would be SO easy to completely neutralize password leakage w
by FiloSottile 12y ago
I hate to be the negative guy, and they were hashing passwords better than 90% of the sites, but it would be SO easy to completely neutralize password leakage when the attacker only has access to the database.
https://blog.filippo.io/salt-and-pepper/ https://blog.filippo.io/salt-and-pepper/
tl;dr: Hardcode a second salt in your application code or in an environment variable. Then a database dump is not enough anymore to do any kind of bruteforce.
It's simple, free and you can retroactively apply it.
EDIT: I addressed some of the points raised in this thread here https://blog.filippo.io/salt-and-pepper/#editedtoaddanoteonrotation https://blog.filippo.io/salt-and-pepper/#editedtoaddanoteonr...
- scott_karana 12y agoI don't see that as a negative suggestion: that's a fantastic idea, and for all we know, a Slack employee will read your post, and make their hashing even better. :-)
- pc86 12y agoBy not implementing the suggestion, presumably. This is rolling your own crypto, which is universally bad. To paraphrase Bruce Schneier, anyone can write a crypto algorithm they themselves can't break. Peppering a password hash destroys any future maintainability.
- scott_karana 12y agoIn a general sense, concatenating a pepper with your salt is NOT reinventing anything at all. (You can rephrase that as "Store pieces of your salt in separate places" which doesn't change or violate any traditional, rigorously tested application of salt in cryptography) There are issues with using it as implemented in some posts here, with nested bcrypts, to be sure, but I think the concept is still fairly sound, though there are certainly implementation pros and cons. ---- As for maintainability: I'm also familiar with crypt(3)-style password hashes, where a prefix uniquely specifies the algorithm (and subvariant) used.[1] Why wouldn't this be fitting here? You can then easily detect, and deal with, passwords that have been tagged with "previous" peppers, such as forcing returning users to change password if a previous pepper was compromised, etc. 1 https://www.freebsd.org/cgi/man.cgi?query=crypt%283%29 https://www.freebsd.org/cgi/man.cgi?query=crypt%283%29 or http://man7.org/linux/man-pages/man3/crypt.3.html http://man7.org/linux/man-pages/man3/crypt.3.html, for some reason I can't find a link to a more comprehensive list at the moment
- Someone1234 12y agoBy that logic, every extra character you concat onto a salt is also "rolling your own crypto." For example if my salt was CrytoRandom(10), and you increase it to CrytoRandom(15) you've just "rolled your own crypto" according to you. If that is not the case then explain the difference between CryptoRandom(15) and CrytoRandom(10) + CryptoRandom(5) (longer salt Vs. salt+pepper). There's a lot of people spreading FUD ("it is unknown!!!") and nonsense (concat two strings is literally rolling your own crypto!) in this thread. I don't know if peppers are worth the dev' time, deployment issues, and additional maintenance (e.g. rotation). However I do know that the people arguing against it here aren't making rational counter-arguments that hold up under basic scrutiny.
- mbrubeck 12y agoPBKDFs like bcrypt assume the salt is a random value that is not re-used and is not required to be secret. You are re-using part of it, and require that it is secret. That's the worrying part, and it's one of the reasons that several concrete proposals posted here have actual security flaws.
- UnoriginalGuy 12y agoMaybe. But that only makes sense if you reduce the length of the salt to add the pepper, which nobody is suggesting. If the salt remains the same length and you add the pepper on top, it won't make the final hash less secure/strong, due to the way hashing algorithms are folded. At worst case scenario you've literally added no security at all with the pepper. There's no rational scenario where it reduces the security when all other things remain equal (i.e. you aren't replacing the salt with a pepper, or reducing the salt's length/complexity for the pepper, etc).
- mbrubeck 12y ago> At worst case scenario you've literally added no security at all with the pepper. Yes, I think this is the most likely failure mode (though not necessarily the only one - crypto can fail in very suprising ways!). But even this is harmful, since you are potentially making changes to security-critical code for no benefit. At best you get more complexity and more chances to introduce bugs, plus a false sense of security.
- randunel 12y agoI generally disagree with hardcoded salts, you should assume everything is compromised in a successful attack. But I'm actually commenting here because I don't see how you can retroactively apply the second salt to a hashed string. Could you please elaborate or share a link? Later edit: I'm referring to your example in your link: salt = urandom(16) pepper = "oFMLjbFr2Bb3XR)aKKst@kBF}tHD9q" # or, getenv('PEPPER') hashed_password = scrypt(password, salt + pepper) store(hashed_password, salt) How do you retroactively apply this?
- willismichael 12y agoYou append the salt to the hash, and then re-hash it. Not exactly pretty, but it works.
- randunel 12y agoHis example doesn't rehash. His example adds the pepper to the initial salt. This is an honest question, how does one apply it retroactively?
- nemanja 12y agoI think you are spot on - you can't apply it retroactively in this case. If you set it up as H(H(pwd, salt), pepper), you could apply pepper retroactively, but that's not what's proposed here nor in the SO question linked above. Also if you do H(H(pwd, salt), pepper), you can successively apply new peppers and make it a bit more maintainable, but I am unclear that it is secure to do so.
- steakejjs 12y agoI don't understand your issue with hardcoded salts. It essentially works the same way as an HMAC. It is some secret material that further complicates the attackers job...It doesn't mean they react to a successful attack in a different way. After hashing the password he is storing the hash along with the users random salt, not retroactively applying the salt a second time.
- 12y ago
- atmosx 12y agoCiao Filippo! That's a nice trick, I've read about it elsewhere but never used, will do for sure in the future! Are you sure that the intruder did not had server access? I mean the info: "We were recently able to confirm that there was unauthorized access to a Slack database storing user profile information." is not enough to deduce that this was an SQL injection (although might very well be). Stay strong :-)
- deleted 12y ago[deleted]
- stiff 12y agoPlease do not do it: http://stackoverflow.com/questions/16891729/best-practices-salting-peppering-passwords http://stackoverflow.com/questions/16891729/best-practices-s...
- atmosx 12y agoThat's a rather comprehensive answer from @ircmaxell over there, hm. Interesting, thanks for sharing.
- baby 12y agoso the downsides are "it's not maintanable" and "don't roll your own crypto". I think they are negligible compared to the upsides.
- mirashii 12y agoNot at all. "don't roll your own crypto" is a downside that can lead to things completely falling apart or weakening the system overall. The real downside is that there's a better, proven way to do the same effective thing, which is make a database-only compromise require additional work, without rolling your own crypto. It also supports doing things retroactively for real (not some of the hacks being discussed in this thread) and key-rotation. All the upsides, with none of the downsides.
- MarkyC4 12y agoThe fact that the pepper can't be changed/rotated far outweighs any upsides
- cpeterso 12y agoYou can change your pepper by double-peppering your existing password database: scrypt(scrypt(scrypt(scrypt(password, salt), pepper2013), pepper2014), pepper2015) https://blog.filippo.io/salt-and-pepper/ https://blog.filippo.io/salt-and-pepper/
- deleted 12y ago
- specialk 12y agoIs there any significant evidence that peppering passwords helps? I've seen arguments for and against peppering out on the big bad internet. Everyone has opinions but there are few people's opinions about crypto that I actually trust. The best article I've seen against this technique is by ircmaxell [0]. Nicely summed up in this sentence "It is far better to use standard, proven algorithms then to create your own to incorporate a pepper." Anyone have source material (academic paper, Bruce "The Crypto God" Schneier blog post) that shreds some light on peppering passwords? I'd be much more interested in how many iterations of bcryprt Slack were using. That has a much bigger bearing on events for me. Anyone at Slack know/want to answer that question? [0] http://blog.ircmaxell.com/2012/04/properly-salting-passwords-case-against.html http://blog.ircmaxell.com/2012/04/properly-salting-passwords...
- rudolf0 12y agoA properly implemented, simple pepper can only help password security and can't hurt it. Obviously you first must be using a good, slow algorithm (bcrypt, scrypt, or PBKDF2 with high work factor), but a pepper will only help you. (Let's assume the pepper is an AES key which all hashes are encrypted with.) Yes, many times a dedicated attacker who has read access to your database will also have read access to your source code or config files, but many times they won't. And if they don't, then they won't be able to crack a single one of your passwords, while even with a modern and proper hashing algorithm they still may be able to crack passwords. Take the scenario of a relatively intelligent hacking or hacktivist group, of which there've been several in the past 5 years. Let's say they're targeting someone they dislike for whatever reason, and find out that person is registered on some forum and decide to compromise the forum. (This tactic of lifting a whole haystack to find a single needle is very common for motivated attackers.) They don't care about any of the other users, they just want to try and crack the hash of one single member and have a full GPU cluster with which to do it. They're also willing to spend weeks trying to crack that one hash. If the user's password isn't particularly strong, it's going to fall no matter what algorithm they used. But if the forum is peppering all of their hashes, and those same attackers can only manage to gain access to the forum's database and not its local filesystem, then their chance of cracking that password goes to 0. This scenario is a bit contrived because odds are motivated and intelligent attackers like these will end up gaining access to the filesystem and reading the pepper with enough time and effort, but the pepper is still an additional defense and means SQL injection alone won't be enough to crack passwords.
- deleted 12y ago[deleted]
- Sami_Lehtinen 12y agoI still wonder what value does password leak have. I changed my password, my old password was: DV1wn3yHk6W-8m9lZNo_ now you all know it, so what? I don't care, I believe you don't care either. On the other hand, if they were after valuable data, they had access to database and the got what they wanted. So the password is much less valuable than the other stuff they might have wanted. Like chat logs which might contain credentials to other services.
- bentcorner 12y agoRight, but many people use the same password for their email account as they do for many other services.
- CameronBanga 12y agoBecause I'm sure everyone uses a long, complex, and unique password on Slack. So nothing to worry about, everyone.
- jessaustin 12y agoIf Slack data isn't important, then it would have been fine to use one's default low-value password, right? So now some attacker has thousands of copies of the word "dragon".
- EugeneOZ 12y agoRecommendations related to Security, should start from words "I'm {name}, known expert in IT Security, my works can be found here: {url}". Otherwise such advices should be ignored.
- rnovak 12y agoCould not agree more. In fact, here is Bruce Schneier's quote[1]: Anyone can invent a security system that he himself cannot break. I've said this so often that Cory Doctorow has named it "Schneier's Law": When someone hands you a security system and says, "I believe this is secure," the first thing you have to ask is, "Who the hell are you?" Show me what you've broken to demonstrate that your assertion of the system's security means something. [1] https://www.schneier.com/blog/archives/2011/04/schneiers_law.html https://www.schneier.com/blog/archives/2011/04/schneiers_law...
- worklogin 12y agoCould not disagree more. Perhaps one should use their own reasoning and the ability to peer-review in conjunction with 'appeal to experience' rather than shut out discussion.
- eropple 12y agoIs your reasoning that of an experienced, competent cryptographer? Because mine isn't. I'm not a cryptographer's peer, either, and I'll bet you aren't either. Step one--nobody said step all, but step one--is establishing your bona fides to determine whether it is worth burning cycles on your idea, because proving or disproving cryptography is very hard and very time-consuming. It is a heuristic that, generally speaking, works pretty well.
- karl_gluck 12y agoNo, his reasoning probably isn't. But without putting words in his mouth, there is this quasi-religious "thou shalt not talk about cryptography" attitude among programmers like crypto is literally voodoo magic. The appeal to experience is an incredibly frustrating part of this. It's like people are willfully ignorant and forcing those of us who may not be experts but also want to have an intelligent discussion to pretend to be idiots along with them.
- zaroth 12y agoThe best summary I've read recently on peppering was posted to the PHC list by Thomas Pornin last week. It's worth quoting in its entirety; Adding an additional secret key can be added generically, in (at least) four ways, to any password hashing function: 1. Store: salt + HMAC_K(PHS(pass, salt)) 2. Store: salt + PHS(HMAC_K(pass), salt) 3. Store: salt + AES_K(PHS(pass, salt)) 4. Store: salt + PHS(AES_K(pass), salt) I have used here "HMAC" to mean "some appropriate MAC function" and "AES" to mean "some symmetric encryption scheme". These methods are not completely equivalent: -- With method 1, you forfeit any offline work factor extension that the PHS may offer (i.e. you can no longer raise the work factor of a hash without knowing the password). With methods 2 and 4 such work factor extension can be done easily (if the PHS supports it, of course). With method 3, you can do it but you need the key. -- With methods 2 and 4, you must either encode the output of HMAC or AES with Base64 or equivalent; or the PHS must support arbitrary binary input (all candidates should support arbitrary binary input anyway, it was part of the CfP). -- Method 4 requires some form of symmetric encryption that is either deterministic, or can be made deterministic (e.g. an extra IV is stored). ECB mode, for all its shortcomings, would work. -- Method 3 can be rather simple if you configure PHS to output exactly 128 bits, in which case you can do "raw" single-block encryption. -- Methods 1 and 3 require obtaining the "raw" PHS output, not a composite string that encodes the output and the salt. In that sense, they can be a bit cumbersome to retrofit on, say, an existing bcrypt library. The important points (in my opinion) to take into account are: 1. This key strengthening (some people have coined the expression "peppering" as a bad pun on "salting") can be done generically; the underlying PHS needs not be modified or even made aware of it. 2. Keys imply key management, always a tricky thing. Key should be generated appropriately (that's not hard but it can be botched in horrible ways), and stored with care. Sometimes the OS or programming framework can help (e.g. DPAPI on Windows). Sometimes it makes things more difficult. You need backups (a lost key implies losing all the stored passwords), but stolen backups are a classical source of password hashes leakage, so if you do not take enough care of the security of your backups then the advantage offered by the key can go to naught. 3. For some historical reasons, many people feel the need to change keys regularly. This is rather misguided: key rotation makes sense in an army or spy network where there are many keys, and partial compromissions are the normal and expected situation, so a spy network must, by necessity, be in permanent self-cleansing recovery mode; when there is a single key and the normal situation is that the key is NOT compromised, changing it brings no tangible advantage. Nevertheless, people insist on it, and this is difficult. The "method 3" above (encryption of the PHS result) is the one that makes key rotation easiest since you can process all stored hashes in one go, as a night-time administrative procedure. 4. Key strengthening makes sense only insofar as you can keep the key secret even when the attacker can see the hashes. In a classical Web-server-verifies-user-passwords context, the hashes are in the database; one can argue that database contents can be dumped through a SQL injection attack, but a key stored outside the database might evade this partial breach. But if the key is in the database, or the breach is a stolen whole-server backup, then the key does not bring any advantage. 5. If you _can_ store a key that attackers won't steal, even if they get all the hashes, then you can forget all this PHS nonsense and just use HMAC_K(pass) (or HMAC_K(user+pass)). The key must thus be envisioned as an additional protection, a third layer (first layer is: don't let outsiders read your hashes; second layer is: make it so that your hashes are expensive to compute, in case the first layer was broken through). P.S. As the inventor of blind hashing (which would have prevented this breach entirely) I have a serious horse in this race. We launch publicly at RSA 2015 in San Francisco. Hope to see you there!
- ntucker 12y agoWe have an approach to this which doesn't modify the password hashing at all, so it can't possibly reduce the strength: we store users and password hashes (currently bcrypt * ) in two separate tables, and the key used to look up a given user's password hash is an encrypted version of their user id. The encryption key for doing this transformation is loaded dynamically at app startup and has some extra security precautions around storing it, so it's not baked into either the source code or a config file. The upshot is that if you get a db dump and are able to brute force some bcrypt hashes, you won't know what usernames they go with. If you get a db dump and our source code, you're still out of luck. If you get ahold of an old server hard drive, you're out of luck. If you root a running server and inspect the process memory, you can obtain this key. This scheme also allows the mapping key to be rolled, which would immediately invalidate all passwords in the system. *we also version our password hash records so we can migrate from bcrypt to a new scheme fairly painlessly if it's warranted in the future.
- simcop2387 12y agoThat's a really interesting idea. I was thinking it might have performance implications but I think that will only apply to the password validation. How do you make sure the mapping key doesn't cause collisions when you roll it to reset everyone's passwords?
- ntucker 12y agoThat's a great point about rolling the mapping key. We would likely be dropping all the rows in the password hash table for such an extreme event anyway, though, since otherwise there's no way to garbage collect the orphaned ones.
- kybernetikos 12y ago> you won't know what usernames they go with But if you've got a list of all usernames (probably a relatively small number) and access to a running system, isn't it easy to just try each password against each user until you find a match? The common practice of limiting logins from a single username wouldn't help with that either.
- mbrubeck 12y agoFrom your blog: hashed_password = scrypt(password, salt + pepper) store(hashed_password, salt) Why aren't you storing the (N, r, p) parameters too? Is it because your library's "scrypt" function automatically encodes all the parameters it uses in the returned string? (This is not hypothetical; it's exactly what many scrypt implementations do.) If so, congratulations: You just stored the pepper bits in your database, because they're part of the "hashed_password" value.
- ghshephard 12y agoIf you care about security then just use an HSM, they aren't that expensive, and eliminate the possibility of a database dump.