New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Security Issue: KDF max iterations is too low #589
Comments
|
Note that when changed, the frontend validation logic will need to be changed here as well: |
|
Minimum iteration should be at least 50,000. |
"dictionary" is the bad word here :) |
|
Seems there is an CVE now for this issue? Any news on this one? |
|
Who did that? It wasn't me. |
|
So when are you going to implement Argon2 |
|
Besides a significant increasing of the current max iterations limit, please think about the possibility of adding Argon2d or Argon2id as an experimental feature for self-hosted environments via setting if the "Argon2 is not in a standard/too young/unproven and unsuitable for this cross-platform project" (yet) point still stands. |
|
Is there a recommended |
|
The numbers you need to raise to fix this vulnerability are the min and default, or the default configuration will remain vulnerable. Modern hardware can do ~22 billion sha256 per watt-second, as I wrote last October. Do you need me to do the basic arithmetic for you or is this an admission of no cryptography engineers on your team? |
|
The title of the report is: "KDF max iterations is [sic] too low", hence why I asked what you felt a better max number would be, so if the issue is the min number, that's different. Our default is 100,000 iterations, the Min allows for higher performance at the user's discretion but the key length combined with the password still makes this relatively secure. We use GitHub issues as a place to track bugs and other development related issues. The Bitwarden Community Forums has a section for submitting, voting for, and discussing product feature requests like this one. Please sign up on our forums and search to see if this request already exists. If so, you can vote for it and contribute to any discussions about it. If not, you can re-create the request there so that it can be properly tracked. This issue will now be closed. Thanks! |
|
Regarding the min number and "official" recommendations... RFC8018 (https://tools.ietf.org/html/rfc8018#section-4.2) mentions it follows the recommendations of NIST 800-132 (https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) which says: But note that's from December 2010. The latest guidelines are NIST 800-63B (https://pages.nist.gov/800-63-3/sp800-63b.html#sec5) which are latest updated on March 2020. They say: The OWASP Password Storage Cheat Sheet (https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2) says the same: So I would suggest to at least increase the minimum to 10,000. |
|
@cscharf The max is too low to allow any secure setting to be configured today. 2M iterations is wholly insufficient. The max needs to be changed, of course. But, it turns out, just upping the max and leaving the default alone will still result in an insecure configuration for almost every user. You'll have to fix the max, too, of course, but the default will need to be changed. Looks like I need to do the math for you. 22 Ghash/watt/sec means that a modest home attacker with, say, 1kW of power (I run more than this in my residential garage) can do 22 Thash/sec. so, with an iteration count of 1, you're looking at 10 seconds to attempt the entire 8 character a-zA-Z0-9 alphanumeric space. Double it if Bitwarden's using PBKDF2-HMAC-SHA256 (I haven't looked at the code lately, I reported this issue a year ago and don't recall what it does). Let's assume it is, so figure 20 seconds for that password space and one iteration. 20 * 5,000 iterations = 100,000 seconds. Just over a day. Up that to 2M iterations, the max permitted, and it's still under 18 months. Recall that this is using only 1kW to perform the attack. Someone temporarily renting say, 10kW of hashpower (still a very small amount of resources) to perform the attack could get that down to 47 days. Either you need to use a much better PRF inside of PBKDF (like Argon2, which has been suggested in another thread), or you need to up the default to approximately 10-100x what the max currently is today. This necessitates increasing the max, naturally, but the minimum should also be 20M or greater to avoid people shooting themselves in the foot. My official recommendations for the settings, given it's 2020: min: 50M Note that these are actually rather risky values still, but are chosen because I doubt using such large values would allow logins in a reasonable period of time on some of the Bitwarden client devices. The correct fix is really to use a modern algorithm, but you've already decided not to do that. As we've learned from the other thread, though, the encryption in Bitwarden is a farce anyway, so I assume this is going to remain closed and unfixed. Be well and good luck! |
|
Note that the OWASP recommendation of iteration count is bad: PBKDF2 is a function that is designed to iterate an internal pseudorandom function (PRF), such as SHA256 or HMAC-SHA256. The underlying PRF's speed is what determines the iteration count security level, not the iteration wrapper PBKDF2 itself. Saying "at least 10k, or maybe 100k" when the context is only "PBKDF2" is meaningless without also specifying the PRF that PBKDF2 is iterating. https://en.wikipedia.org/wiki/PBKDF2 You guys should know all this already, because you're in the password manager business. It's a bummer you don't. |
|
@cscharf these iteration settings could perhaps be enforced through the new policies, it would allow an organization to improve its users' security (and its own security...). |
|
I have gone through the festivities of 3 issues being raised and thrown around on Bitwarden. So let me first start with the comment on the OWASP CS on Password Storage:
If you need more than 100k, then by all means, don't refer to a cheat sheet for DEVELOPERS. If you're a cryptography expert, this CS is not for you. It's for the developers without a cryptography expert. Throwing random recommendations to 50M as a minimum value that is supposedly running on a RPi or an old mobile phone is not something that any of the security community will take or accept. The CS recommends the Bcrypt function because it's the simplest to implement for developers, it's robust, and it's secure. You can implement argon2? Go ahead, we say that as well across the CS. Mess up one variable in argon2 and you have all hell wreaking havoc in your system (either by DOSing it, or by being too fragile and actually weaker than bcrypt) Second, the CVE you keep referencing, and I quote:
The KDF in discussion is PBKDF2-SHA256, which is a standard. I have no idea who created that CVE, but it shows how ill-informed they are. "Potentially unwanted". Just read it. What is this? Why is it unwanted? Third off, stop throwing shade on Bitwarden like you own shares in this software! Oh, and let's stop talking about 8 chars passwords too. That's a whole different issue in itself. If someone sets a password to 8 chars then no PHF is going to save them. How about we start talking with 12-16 chars? That sounds much better as a base. Disclaimer 1: I was one of the reviewers of the password storage CS, and we took the references and words of the hashcat team on how this should be worded and written. If you want the CS to be updated, go and open an issue with a recommendation. Stop throwing beef randomly everywhere. Have some respect for the HUGE work being put everywhere. Your comments are technical and great, the delivery is not. Disclaimer 2: I am not affiliated with bitwarden nor care on what they actually action on this. I have just seen this being thrown around in bad ways. Open issues (that provide what you'll be doing) and open PRs, help them improve if you actually care. |
|
I am a bitwarden user, so I have quite a bit more at stake from their poor practices than if I were just a shareholder in the company. Regardless, they are more interested in having a shiny product than building secure cryptography software, so I’ve already unsubscribed from the thread, will be migrating my own use away, and migrating the client fleets I’ve steered toward them in the past away. Please don’t mention me in these threads any longer. |
|
I would understand hesitance if this was for adding argon, but why are you guys so hesitant to increase the maximum iterations (or I mean, remove it too, if you prefer). This is (more or less) as hard as changing a few variables (or one if you make this well). I really like the idea of a self hosted password manager but using pbkdf2 is an unexcuseable compromise when you then refuse to do anything about securing it. |
@sneak
I found it a bit convenient that you chose only alphanumeric and a length of 8. This is your master password you're concerned about and you want to secure it with what would be considered a weak password with low entropy? (~47.6 bits) I wouldn't be surprised if it's much weaker by being a single word all in lowercase or matching one of the top 1M passwords. The issue isn't on BitWarden, it's on your own security practices.
How much is that going to cost in $? How much resources are being allocated by this attacker for 47 days to solely attack your password? Are they likely to perform an attack like this for 47 days on numerous users, or are they specifically targeting you? If you assume the likelihood of that is high or this is a well funded attacker with no concerns about wasting resources then what is the best way for YOU to defend against this attacker? Is it: A) Use a weak password and pray for open-source software to use sufficient iterations to my satisfaction with their KDF. You chime in here with a bunch of info to push your interests for A, and choose to do so rudely. Choose B and be on your way. Such an attacker has cheaper avenues to attack you with. It would cost them less to:
I have an i5-6500 Intel CPU. That's 4/4 cores/threads. I just did 20M iterations (small rust program running PBKDF2-HMAC-SHA256) and it took 17 seconds. Your advised minimum of 50M iterations takes 44 seconds long. So by default you're wanting to impose about 3 minutes of wait time from my password to be hashed before I can proceed?..75 minutes for maximum? You need to account for UX here. You're pointing fingers that iterations are too low and thus your weak password can be attacked in 18 months or less by your given math. As we've clarified, using a more secure password will give you the same benefits you're wanting without imposing massive delays on other users UX. 2 million iterations takes about 2 seconds with my CPU, 90ms for 100k iterations. I imagine many self-hosted deployments of BW are on weaker/restricted hardware where that'd take a bit longer. This is perfectly fine default for good UX while the KDF is still doing it's part to increase security effectively, it alone should not be relied on to secure your password, add more entropy to your password.
I hope those that land on here don't take this guy seriously. He's ranted about so much already trying to make BW look bad when they're actually doing well. Argon2id would be good as a configurable alternative, perhaps even scrypt if the justification for adopting argon2 is not going to budge. The same logic applies though, KDF slows the hashing process down which discourages attackers from bruteforce guessing. You can keep extending the time to hash, or you can increase the strength of your password. Extending the time is beneficial with many users where password strength may be poor, but this is your master password just for you, on a self-hosted service. You're going to get so much more security out of a stronger password than relying heavily on a KDF slowing an attacker down. For those not in the know:
|
@ThunderSon Like PBKDF2 not being setup for 1 iteration by default and leaving it up to the user to suss out, I would imagine an argon2 implementation would also have a reasonable default. If the user wants to tweak parameters because they know better (or think they do), that's on them. You can already bump PBKDF2 up to 2M that is supported and DoS the service by locking up CPU? What were you seeing as a different attack with argon2, memory? Correct approach would be to have some rate limiting or other defenses restricting access to the service. I don't see that as a compelling reason against argon2 support (but I do agree not to demand and expect it, if someone really wants it bad enough they can contribute or sponsor the feature). Regarding weaker than bcrypt, that's 4KiB RAM, only difference then would be time when comparing no? That's something BW could provide via the UI as feedback if the user isn't experienced enough to make that choice, but at the same time they shouldn't be messing with such parameters if they don't know what they're doing. bcrypt itself has it's own issues (though I doubt many would run into them, I did see some BW community thread talking up how great emojis in the master password would be for boosting entropy, which would be misleading).
I think it was pretty evident they didn't even consider the UX impact of that many iterations and were only thinking of securing their weak password from an attack which made no sense. |
@gidoBOSSftw5731 Do you believe it is the right thing to do and makes the security better in the correct way? At 2 million iterations, you'll be waiting ~2 seconds depending on machine performing the hashing. You would like to further increase that? The user advised a max of 5 billion iterations, which on my machine would take 75 minutes. If you're not able to grasp KDF iterations purpose, then you would see the maximum as the most secure option and possibly opt for that. Only to find that BW has become unresponsive for over an hour and doesn't seem to be liking your master password, so you raise an issue on github about it being buggy. 2 million is plenty. The complaining user with all their math and statistics to sound convincing at making BW look at fault was clearly describing the time and resources required to attack a very weak password. Do you think a 62^8 keyspace password (alphanumeric upper/lower case, no symbols, 8 characters long) is a good choice for your master password that secures all your other passwords? My response to that user details small differences that dramatically change the time to attack based on their logic. It's not weak number of iterations here, it's a weak password. Should BW encourage using weak passwords? Or would it be better to educate such a user instead? (not saying that they do, but it's a much better fix to have that setting mention if the max value isn't sufficient, please consider a stronger password as it'll be more effective).
What aren't they doing that they should? I think I've just conveyed why adding more iterations isn't the right approach when you want to secure something. |
|
I don't believe more iterations is going to be the solution to all of this, but instead moving to something that does not have the hardware to make it so easy to brute force, like argon2, scrypt, or other similar password algorithm that has more precautions than pkdbf. My argument on not capping maximum iterations is "if you aren't going to implement a better key derivation function, atleast let us secure the current implementation more." This as an artificial bottleneck just seems unnecessary, if you want security you'll wait 10 sec or whatever for your password and if not you probably don't even know what pkdbf is since you're s normal user. |
It's not easy to brute force though, just don't use a weak password to begin with? Argon2 can be configured nicely but if your password is
2 seconds per attempt on my PC is slow. The math above shows it taking many months with more capable hardware to exhaust the weak password key space. It's already not worth attacking that unless you're being targeted directly. Getting your password may be cheaper and faster by alternative approaches, and if you honestly care about your password strength security beyond what 2 million iterations is providing you, then simply make a slightly stronger password, it'll be far more effective without degrading your UX even further....nobody wants to wait 75 mins to hash the master password. This is like arguing 2048-bit vs 4096-bit RSA certificates when 2048-bit RSA is very secure with no tangible benefit really to use 4096-bit, especially as a default, some even thought 8192-bit RSA was more secure and worthwhile without valid justification of how. |
|
Seems like there are 2 places where KDF iterations can be tuned. For the master password itself : server/src/Api/Controllers/AccountsController.cs Lines 65 to 69 in 3877b89
And also here : server/src/Core/Utilities/ServiceCollectionExtensions.cs Lines 247 to 251 in 3877b89
Seems like it defines the number of iterations for the Identity server. Many thanks |
|
Sorry @Mart124 , I'll do my best to answer these:
This is simply the "Default" when a KDF is not set for the user's email address passed in during pre-login. This code will return the default if the user hasn't overridden them themselves in the settings.
This is the default password hasher settings used when comparing password hashes server-side for things like validation when changing your email address ( |
|
Thank you again @cscharf, perfectly clear, as usual
If I may, what about this idea ? |
Done! |
|
Just a tiny ping here, to ask for some news regarding this security feature :) |
|
Thank you very much @cscharf, understood, good news is that it's still in your backlog, perfect :) |
OWASP specified different recommendations per hash, however the numbers seems to be not very rigidly derived and they are targeted do to usage in online authentication databases, not for offline crypto vault KDF. So you might say, they are bad:
But those are roughly 0,1 - 1s on most clients or GP servers, so it’s a good start for an default (but the maximum should be allowed higher, especially with expected growth). 2Mio HMACSHA256 iterations however looks reasonable. If you have higher demands, don’t use a online service login with the same password. -> server does not care about DOS. BTW while PBKDF2 image is rather bad, numbers from the field don’t look that bad. Even with most recent High End CPUs the most optimized hashcat implementation displays bitwarden as only one of few in the kH/s range mit modest iterations (1/20 of max!)
It might not be so positive for purpose build hardware, but even expensive top of the line hardware does not a shame PBKDF2. Source https://gist.github.com/Chick3nman/32e662a5bb63bc4f51b847bb422222fd |
server/src/Core/Models/Api/Request/Accounts/KdfRequestModel.cs
Line 22 in da5c385
From bitwarden/jslib#52 :
The text was updated successfully, but these errors were encountered: