SHA256 is a terrible choice for a PBKDF in 2019. #52
Comments
|
This has been discussed before. See: |
|
If we're stuck with SHA256 as you senselessly claim, it would be nice to be able to specify a reasonable number of iterations so that the weaknesses in SHA256 as a PBKDF can be mitigated. However, that workaround is specifically prohibited by Bitwarden, restricting it to 2M iterations. Modern SHA256 hardware1 can do 22,200,000,000 hashes per watt-second, so a single unit operating at 1000W can bruteforce 11,100,000 passwords per second with the maximum iteration count allowed. The default iteration count is much less, allowing for practical and efficient dictionary attacks with hardware. Looks like this was previously discussed2, but this isn't a feature request, this is security vulnerability report. If you're going to insist on SHA256, the iteration count should default to at least 10M, and should permit up to 100M as a configuration option. Really, though, using an appropriate password-to-key derivation function is the correct solution here. Failing that, at least remove the 2M limit which forces SHA256 to an insecure mode. |
|
Is there any ASIC mining hardware that can be used for password cracking? |
|
Argon2 is strongly recommended. It is highly resistant to side-channel attacks, and continues to be well regarded. If the choice to continue to use PBKDF2 relating to FIPS, could we at least get the option? Argon2id with t/p=1, and a reasonable M setting (since we're also talking mobile devices here) should be a really good choice. This is the one security-specific change keeping me from switching over a large number of users to Bitwarden from Dashlane (which uses Argon2). Can we help the process? |
|
from @kspearrin in the above linked issue:
Argon2 is fully specified, and is a standard. How old does it need to be to be used? On which platforms does it need to be implemented, and which are as yet “unproven”? What is “proven” in your view: a full test suite? Please tell us the specific hoops that must be jumped through, and we will jump through them. I am happy to write some comprehensive test suites for all languages/platforms required by Bitwarden, although I am reasonably certain they already exist. How old must it be? What platforms are required? Are full test vectors “proven” enough for you? |
|
const hash = await this.cryptoFunctionService.pbkdf2(key.key, password, 'sha256', 1); if you look at the last attribute of the pbkdf function, you shell find the hash iterations is ONE and the random salt is the user password..... |
|
It's making a (poorly named) "password hash" from the prelogin key (which is generated from the master password with the proper iteration count), so it's okay on its face. HOWEVER, the iteration count is provided by the server! If the server were to tell the client the iteration count is supposed to be 1 (regardless of the real value), the prelogin key would be brute-forceable, and also the password hash derived therefrom would further be brute-forceable to recover the master password. If the server were to then log this hash value on login attempt, the server admin could straightforwardly bruteforce the master key and decrypt the entire vault.
jslib/src/services/auth.service.ts Lines 207 to 210 in cd46f64
jslib/src/services/auth.service.ts Line 237 in cd46f64
@kspearrin Please advise re: security issue. |
|
@sneak This is incorrect. The clients enforce a minimum iteration count. See https://github.com/bitwarden/jslib/blob/master/src/services/crypto.service.ts#L311 |
|
Ahh, I see, you're right - I missed it inside of makeKey(). Still, the minimum of 5000 iterations still means 4.4 million bruteforce attempts per watt-second, or 4.4B per 1000W per second, meaning the entire alphanumeric a-zA-Z0-9 space for an 8 character password can be bruteforced in half a day. Please increase the minimum by 10-100x. (You will of course have to have the clients opportunistically update first.) Please also increase the server-imposed maximum limit by at least 100x as well. |
|
This is really just a band-aid, though. I am more than happy to do whatever legwork you deem necessary to polish libraries and test suites for whatever languages and platforms you deem necessary to switch to using a modern KDF. |
|
Maybe it's possible to switch to this library: https://www.npmjs.com/package/argon2-browser Since it's already used by another Vault (KeeWeb). |
|
I think Argon2 would indeed be a preferred alternative. As mentioned before, KeePassXC and other KeePass variants use it to great effect. It also has some solid tunable parameters to add complexity rules. |
|
I've created a (planned to be temporary) fork at https://github.com/michaelsmoody/bitwarden-jslib-argon2. If you would like access to help move to Argon2, let me know. The goal is simply to do the work, and create a PR for upstream, rather than being a permanent fork. |
|
I'm going to quote my post from the forum feature request about this here:
|
|
As mentioned, I also agree. I'm open to PRs (merge requests) for the fork I created. I've started work to integrate the well-supported libsodium into the Bitwarden source, allowing Argon2 to be used. I'm open to other suggestions if there's a superior alternative implementation (well supported, properly licensed, existing library, etc). |
|
Ping @kspearrin? I’m still willing to do this work for free if you specify it so I know my efforts won’t be wasted if I work to the spec. |
|
@sneak (@michaelsmoody, et. all.), we would absolutely accept an update to Bitwarden clients that added an option of using Argon2 to the supported list of algorithms. Please move comments, design discussion topics, package (npm, etc.) decisions/questions, etc. to the community forums topic for the same. Kyle and I will ensure this is on our radar so we can help provide PR reviews, feedback, etc. (updating there as well) |
|
The discussion forum indicates that as of three days ago, nobody inside of Bitwarden is working on this security issue. https://community.bitwarden.com/t/switch-to-argon2/350/32?u=sneak I offered to do the work for free if you'd just specify the project precisely to ensure that the work I do will not be wasted, but that's not happened in a year, neither here nor on the forum. Could you please give us some hint that Bitwarden-the-company cares about the security of its product? This is a major issue. The current KDF's use of an extremely low iteration count (with the server actively prohibiting a high enough value) is actually a vulnerability that has existed for over a year since I reported it: Switching to Argon2 (this issue) would fix it, but so would fixing 589 to just not use an insecure low iteration count for the current KDF. |
|
@sneak ,
You're absolutely correct, we are not working on this feature request. We are open, available and willing to answer questions, provide feedback and support the community, including you, who have offered to work on this, however. The Bitwarden team is a small (but growing) team with a lot of competing priorities and as a primarily open source organization we are supported in requests such as this by our community involvement which we are exceptionally grateful for. Security is a priority, but we currently already offer the industry standard means of cryptography within our product today, so more advanced or hyper-secure algorithms like Argon2 are considered a feature request/enhancement and not a mission-critical the "world will end" without it kind of thing. We also actively support, remediate and disclose items that come through our HackerOne program (and are starting to evaluate a private bug bounty program with HackerOne as well).
I'm afraid I'm not clear on your needs in order to get started or to assist in contributing to the Argon2 effort. There are other community members that have also offered and to my knowledge have already started an implementation, I would highly encourage you get with them (such as @michaelsmoody ) to see where they are and how you can help. If there are specific needs, such as technical direction, specifications, assistance with your development environment, location of certain constructs within the code, application or solution, we have a Gitter channel for developers, we have community forums (which you have also posted to) as well as other resources for getting the assistance you need in developing against the Bitwarden platform. If you are looking for detailed specifications, requirements or other documents from the Bitwarden team on exactly what to build and how to build it, we honestly don't even do that for our internal development team as we use an agile approach to PoC, test, revise and review cycles. I would highly recommend some rapid prototyping with a draft PR to be open for comments, feedback, etc. |
|
@sneak Would you be interested in speaking with me about my efforts to implement libsodium? I would also love to sit and work on a design document for the planned change (I too have asked for some guidance as to what would be accepted, but it basically was: "whatever you create as long as it's properly licensed and coded the same way"). To that end, I'm working on integrating the excellent cross-platform libsodium, and I'm working my way through the flow to determine what would be necessary to allow configurable hashing, password hash conversion (en masse), sync'ing, etc. If you're interested, let me know. The "step one" problem of swapping out the current function calls is straightforward enough, it's the "everything else" that's taking some time to map out. |
|
What about the vulnerability I reported last October? Fixing this issue would resolve that one as well. Even if you’re not interested in adding this feature, when do you plan on fixing the vulnerability (CVE-2019-19766)? |
|
As far as allowing a higher max iterations for KDF, I'll respond in the other item @sneak , thanks. |
|
I work for a competitor of Bitwarden's (1Password), and I hate PBDKF2 as much as anyone (See my PasswordsCon talk from 2013). But I will outline why we are still using PBKDF2-SHA256 despite being fully aware of its limitations, and why we don't put the number of iterations under user control
With all that said, where I work, we continue to explore successors to PBKDF2-SHA256. I thought we would be able to roll one out before now, but I was wrong. And because I know I can be wrong about such guesses, I am not going to make my guesses of a time line public. And while I won't speak for Bitwarden, there are two over-all points from the above that may affect their security thinking
Those two facts should play into decisions about development priorities. |
|
Three important things to note:
I myself switched to using bitwarden_rs, which is compatible with the bitwarden clients. It's in rust and is easy to patch to permit a higher kdf max iteration count, and has the added benefit of not costing anything for use of the server. |
This is really all you needed to write. |
I think this is slightly misleading. The ASICs used for bitcoin mining are optimized for hashing bitcoin block headers (80 bytes of data / 2 sha256 blocks). It's unlikely they could retrofitted by an end-user to crack KDFs. There's a ton of esoteric optimizations baked into them specifically for bitcoin: e.g. the block header's nonce is in the second sha256 block, meaning asics are optimized for hashing the first block, saving that state, and incrementing the nonce in the second block (which is pre-padded to 64 bytes), and then hashing it to reach the final state. The first state can be re-used as long as nonce space is available. There's also another round of hashing that needs to be done once this process is completed. This is all implemented in hardware and not really changeable. Perhaps the actual threat is that a mining hardware vendor may use their expertise to create some kind of chip to crack PBKDF2 (though, I suspect that is not worth their time or energy). |
|
I'm not a fan of PBKDF2 (although I do maintain implementations of it alongside Argon2, scrypt, etc). That said, this statement is misleading:
Bitcoin PoW uses SHA256d, i.e. Furthermore, ASICs optimized for Bitcoin usage further integrate the structure of Bitcoin block headers, and are very much not generally reusable for anything else other than solving Bitcoin PoW. Edit: haha wow, @chjj just posted a nearly identical comment at the exact same time I did. Serendipity! |
Hey, please forgive me if this next paragraph is known to you (likely is), but I would hate for people to misread your comment and unknowingly write off KDFs that use computationally intensive hashes. One of the child comments have been linked on HN and is likely to attract people unfamiliar with this area of cryptography. Onlookers, PDKDF2 and it's variants work with inefficiency as a chosen variable. An excellent writeup and intro to the topic (along with a foray into optimizations) can be found by reading @ctz's writeup here. |
|
@jpgoldberg, may I ask what sort of gotcha's you are concerned about with WASM? Perhaps we could talk offline or you could direct me to a post somewhere? |
|
Hello! If i look in PRs here https://github.com/bitwarden/jslib/pulls - i don't see any activity on this exactly? Excuse me if I bothered you, but I have been interested for months now, Edit: Ok so the Bitwarden team isn't working on this, but i still pinged other users maybe? Last Edit: I checked out BW forums https://community.bitwarden.com/t/switch-to-argon2/350 - only 127 votes as of ~ Aug 2021. It might take some time. |
|
Hi @sneak, |
|
Just switch to Argon2 |
|
Ultimately, that's still the thing that I intend to do. I got seriously sidetracked by other things, and bitwarden reorganized their repositories as well. With that said, I haven't forgotten about it, and while @jpgoldberg made entirely valid points about PBKDF2-SHA256 and the iterations, those don't apply to Argon2 at all. WASM is quite well tested cross-platform, and with the recent deprecation of older platforms for many many reasons (RE: SSL certificates, such as CA/B and their multitudinous changes to lifetimes, LetsEncrypt and their changes, expirations of root certificates, Apple moving older devices to legacy/EOL status, and Microsoft doing the same, etc, etc), the fact is that there are few reasons why not to use it, given that it is now nearly a decade old, with many well-supported, and well-tested implementations. I'm certainly open to opposition, however. |
|
While we would normally wait for 2 weeks, on this issue in Github I'm going to go ahead and close it so all future conversation moves to our community contribution forums here. Thanks @orangesunny & @michaelsmoody. My understanding is there would still be interest in this, however the Bitwarden team won't be focusing on the implementation ourselves any time real soon, but are happy to work with any community contributions of the same. |

https://github.com/bitwarden/jslib/blob/cd46f64993545a1cb772e2f6a2137a675554f3c3/src/enums/kdfType.ts
It looks like the only supported choice for a PBKDF is SHA256. This is possibly the worst choice available for a password-based KDF, as a PBKDF should be relatively slow, and SHA256 is perhaps practically the fastest hash function on earth due to optimizations made for Bitcoin (e.g. cheap ASICs and suchlike). Even iterated, it's way too fast, and only getting faster.
I was evaluating Bitwarden as a potential replacement for Dashlane (Dashlane sucks) but this is a real non-starter for me. Please up your KDF game. It's 2019.
Additional reading:
https://medium.com/@mpreziuso/password-hashing-pbkdf2-scrypt-bcrypt-and-argon2-e25aaf41598e
https://medium.com/@mpreziuso/password-hashing-pbkdf2-scrypt-bcrypt-1ef4bb9c19b3
TL;DR: Use Argon2. https://www.npmjs.com/package/argon2
The text was updated successfully, but these errors were encountered: