Project

General

Profile

Actions

Bug #12800

closed

Suboptimal Password Hashing

Added by Sam K about 2 years ago. Updated about 2 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Authentication
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:
Plus Target Version:
Release Notes:
Default
Affected Version:
2.6.0
Affected Architecture:

Description

This bug relates to Todo #10298: https://redmine.pfsense.org/issues/10298

The default password hashing algorithm has been changed from bcrypt to SHA-512. This significantly increases the risk of password hashes being cracked if they are obtained by an attacker.

Rough benchmark data suggest that SHA-512 hashes can computed more than two million times faster than bcrypt password hashes:

https://crypto.stackexchange.com/questions/46550/benchmark-differences-between-sha-512-and-bcrypt

bcrypt : bruteforce : ~                              400 H/s
         Wordlist + dive.rule :  ~                   550 H/s

sha512 : bruteforce : ~          870 MH/s ->   870000000 H/s
         Wordlist + dive.rule :  ~ 640 MH/s -> 640000000 H/s

Factor sha512 -> bcrypt : 1:1589473

In other words, a password hashed with bcrypt that would have required 24 hours to crack would require less than a second to crack if hashed with SHA-512 instead.
The references made to the Commercial National Security Algorithm (CNSA) Suite are not applicable to password hashing. As stated in the abstract of FIPS 180-4:

“This standard specifies hash algorithms that can be used to generate digests of messages. The digests are used to detect whether messages have been changed since the digests were generated.”

This is an entirely different use case to password hashing, which FIPS does not cover. The hashing recommendations made in FIPS are only appropriate for message digests, where speed, consistency and a low probability of collisions are vital. For password hashing, the slowest practical hash function should be used to increase the computational effort required to crack passwords.
A more secure password hashing approach should be implemented, further guidance for which is included below:

https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html

This could likely be achieved by using the password_hash PHP function, also linked below.

https://www.php.net/manual/en/function.password-hash.php

This issue also appears to affect FreeBSD at an operating system level.


Related issues

Related to Todo #10298: Use SHA-512 for user password hashesResolvedViktor Gurov02/27/2020

Actions
Related to Feature #12855: GUI option to select the user password hashing algorithmResolvedJim Pingle

Actions
Actions #1

Updated by Gaige Lama about 2 years ago

Sam Kirkman wrote:

This bug relates to Todo #10298: https://redmine.pfsense.org/issues/10298

The default password hashing algorithm has been changed from bcrypt to SHA-512. This significantly increases the risk of password hashes being cracked if they are obtained by an attacker.

Rough benchmark data suggest that SHA-512 hashes can computed more than two million times faster than bcrypt password hashes:

https://crypto.stackexchange.com/questions/46550/benchmark-differences-between-sha-512-and-bcrypt

[...]

In other words, a password hashed with bcrypt that would have required 24 hours to crack would require less than a second to crack if hashed with SHA-512 instead.
The references made to the Commercial National Security Algorithm (CNSA) Suite are not applicable to password hashing. As stated in the abstract of FIPS 180-4:

“This standard specifies hash algorithms that can be used to generate digests of messages. The digests are used to detect whether messages have been changed since the digests were generated.”

This is an entirely different use case to password hashing, which FIPS does not cover. The hashing recommendations made in FIPS are only appropriate for message digests, where speed, consistency and a low probability of collisions are vital. For password hashing, the slowest practical hash function should be used to increase the computational effort required to crack passwords.
A more secure password hashing approach should be implemented, further guidance for which is included below:

https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html

This could likely be achieved by using the password_hash PHP function, also linked below.

https://www.php.net/manual/en/function.password-hash.php

This issue also appears to affect FreeBSD at an operating system level.

It's using CRYPT_SHA512 instead of plain SHA512 which has a default of 5000 rounds. However, this is still a downgrade in terms of security over using password_hash(). Also, random_bytes() should have been used instead openssl_random_pseudo_bytes(). Why downgrade security to satisfy the CNSA Suite? Is there some governmental requirement for this? If it's to be FIPS-compliant, is the entirety of pfSense compliant? If pfSense isn't compliant why change this at all?

Actions #2

Updated by Sam K about 2 years ago

Gaige Lama wrote in #note-1:

It's using CRYPT_SHA512 instead of plain SHA512 which has a default of 5000 rounds. However, this is still a downgrade in terms of security over using password_hash(). Also, random_bytes() should have been used instead openssl_random_pseudo_bytes(). Why downgrade security to satisfy the CNSA Suite? Is there some governmental requirement for this? If it's to be FIPS-compliant, is the entirety of pfSense compliant? If pfSense isn't compliant why change this at all?

That is a good point - I have corrected the comparison below:

Hashmode: 3200 - bcrypt $2*$, Blowfish (Unix) (Iterations: 32)

Speed.#1.........:    12840 H/s (18.80ms) @ Accel:1 Loops:32 Thr:16 Vec:1

Hashmode: 1800 - sha512crypt $6$, SHA512 (Unix) (Iterations: 5000)

Speed.#1.........:    77688 H/s (83.58ms) @ Accel:8 Loops:256 Thr:1024 Vec:1

This makes CRYPT_SHA512 "only" around 6 times easier to crack than bcrypt, but that is still a downgrade.

Actions #3

Updated by Viktor Gurov about 2 years ago

  • Related to Todo #10298: Use SHA-512 for user password hashes added
Actions #4

Updated by Steve Thomas about 2 years ago

sha512crypt introduces a DoS because it runs in O(pwLen^2+pwLen*cost) time. On a i5-6500, a 14000 character password takes ~1 second, 28000 takes ~3 seconds, and 56000 takes ~11 seconds.

P.S. The new settings are ~120x weaker (sha512crypt 5000 rounds vs bcrypt cost 10). Note Hashcat benchmarks sha512crypt with 5000 rounds and bcrypt with cost 5. To estimate speed for bcrypt: benchmark*(1+2*2^5)/(1+2*2^cost). That means for your GPU bcrypt cost 10 is 407 H/s. RTX 3080 benchmarks (325300 H/s vs 2644 H/s (for cost 10, note 2644 H/s = 1.1*2404 H/s because this benchmark was before a 10% speed increase in bcrypt)): https://gist.github.com/Chick3nman/bb22b28ec4ddec0cb5f59df97c994db4.

Actions #5

Updated by Royce Williams about 2 years ago

Steve's benchmark information is more representative of real-world attack than the earlier examples, because GPU attack efficiency is much greater than CPU, and because the bcrypt cost that was previously used is 10, compared to the default cost sha512crypt work factor (5000 rounds).

Demonstrating that, using an actual real attack against real single hashes, using six GTX 1080s, latest hashcat from GitHub, bruteforce attack of any 7 bytes, bcrypt cost 10 vs sha512crypt default cost:

$ hashcat -V
v6.2.5-236-gcae2562c0

$ cat test.bcrypt10 
$2a$10$X48aAhYuu2nNP/YXDSAXNeUDaigg7qCg8b9r2w6DgtFt5eHpkKYUm

$ hashcat -w 4 -O -a 3 -m 3200 test.bcrypt10 ?b?b?b?b?b?b?b
[...]
Time.Started.....: Tue Feb 15 14:09:45 2022 (30 secs)
Guess.Mask.......: ?b?b?b?b?b?b?b [7]
Speed.#*.........:     4265 H/s

$ cat test.sha512crypt
$6$ltQVG.yh2nyDG/dt$Z3fcj7pU0mcOt8Tp7z5yH7jaFEbWdzNSQnuuLpt/n.zc9dvzEmnQBtNwbGUL0VCT4rE1eQmCt4u2i2IrZrUUR1

$ hashcat -w 4 -O -a 3 -m 1800 test.sha512crypt ?b?b?b?b?b?b?b
[...]
Time.Started.....: Tue Feb 15 14:12:36 2022 (30 secs)
Guess.Mask.......: ?b?b?b?b?b?b?b [7]
Speed.#*.........:   857.3 kH/s

That's about 200 times as fast. Other attacks will have different absolute speeds, but should be similar in relative performance to each other.

As to the compliance angle, agree 100% that the NSA reference is totally unrelated to password storage. NIST 800-132 only lists the properties of an acceptable password-hashing algorithm. It lists PBKDF2 as an example that is conformant, but only as an example. I see nothing in the standard that precludes using bcrypt, and cryptographer Thomas Pornin concurs. - and FIPS 180-4 specifically only addresses the "for computing a condensed representation of electronic data" use case.

As long as it's acceptable for passwords to be capped at a length of 72 bytes (usually fine even for passphrases), bcrypt is a stronger choice that balances resistance to attack and UX performance (cost 10 is usually acceptable for <.5s login latency).

Also note that sha512crypt is a poor choice for potential side-channel reasons. Aaron Toponce has a good writeup here:

https://pthree.org/2018/05/23/do-not-use-sha256crypt-sha512crypt-theyre-dangerous/

Actions #6

Updated by Royce Williams about 2 years ago

If this change is for potential compliance purposes, such as FIPS, a good compromise might be:

  • Expose a UI element to allow users to toggle the compliance mode on and off (similar to how other platforms do)
  • Increase the number of rounds for sha512crypt to take around .5 seconds on an average platform
  • Optionally, dynamically benchmark platform speed, and set the number of rounds to match that .5 seconds mark
  • When enabling the mode, give the user a brief friendly warning about the trade-offs (including the known DoS issue, which may be a non-issue for many users depending on use case)
Actions #8

Updated by Jim Pingle about 2 years ago

  • Related to Feature #12855: GUI option to select the user password hashing algorithm added
Actions #9

Updated by Jim Pingle about 2 years ago

  • Subject changed from Insecure Password Hashing to Suboptimal Password Hashing
  • Status changed from New to Closed
  • Assignee set to Jim Pingle

Moving this over to a feature request to give the user a choice between bcrypt and SHA-512: #12855

Also changing the wording of the title since it's hyperbole. It's not "Insecure" per se, but bcrypt is more secure. SHA-512 with the default number of rounds is the default hash type on FreeBSD and some Linux distros. If it was that dire of a situation nobody would still be using it as an OS default.

Actions #10

Updated by Royce Williams about 2 years ago

Sounds like a solid way forward - much appreciated!

I do want to point out that whether or not something is dire, vs whether or not is has generated clamor, are historically not necessarily well correlated. :D There is always latency in uptake vs awareness. For example, the default for many Unix-likes was descrypt, and then later md5crypt, for some time - even well after they were demonstrated to be poor. It takes pressure on multiple fronts, such as this one, to raise awareness enough to stimulate action.

And that's just about what to move on from. The counterpressure is that the crypto folks wisely advise everyone to not rush headlong into the newest crypto / hash. So it also takes time for consensus on what to move to. :D

And all of the above supports the direction you're taking here. Given the constraints, enabling users to make an informed transition is a robust way forward, and is much appreciated.

Put another way: enabling a measured transition is the best way to fix it before it becomes dire. ;)

Actions #11

Updated by → luckman212 about 2 years ago

Really like the discussion here! Thank you Royce Williams for all of your analysis which was very informative. I think giving users the choice (and also not auto-converting them from bcrypt to SHA512) is the right move, and would satisfy all parties. I'm not a tin foil guy and am sure for 99.999% of users, SHA512 is adequate, but who am I to tell someone they can't put a stronger lock on their door?

Actions #12

Updated by Sam K about 2 years ago

As the original reporter, I'd like to echo Royce's words above and thank you for incorporating this into a feature request.

I would also like to apologise for my initial hyperbole, which was based on an incomplete understanding of the issue at hand. I am therefore very grateful for the subsequent contributions from the community that have clarified the real-world risk present here.

Actions #13

Updated by Royce Williams about 2 years ago

In #12863, I propose a (surprisingly simple) solution that dramatically increases the strength of the sha512crypt hashes, with very little overhead or complexity, and dynamically adjusts to the power of each platform it's run on.

Actions #14

Updated by Tom Sham about 2 years ago

sha512crypt should be deprecated and removed in favor of better and more established options. It is a mistake to default it in pfSense in the first place. If we need a NIST compliant option, PBKDF2 with SHA256/512 HMAC is the right candidate. That is also what NIST recommended: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf and https://pages.nist.gov/800-63-3/sp800-63b.html (section 5.1.1.2).

Actions

Also available in: Atom PDF