I'm not going to waste any time here - just going to dive right into it.
I'm proposing a formal upgrade of the cryptographic process used to securely store passwords for users on Cloudron, administrator included.
The current algorithm, which is (to my knowledge), PBKDF-SHA1 is extremely insecure.
In fact, based on the claims made by Google's researchers nearly three years ago, SHA-1 should be considered broken
I don't want to sound 'alarmist' or like a 'concern troll', but given the fact that passwords are close to the "last line of defense" when it comes to protecting information / sensitive data / etc., this is an issue worthy of labeling as 'critical'.
The weakness of the cryptographic hash algorithm used for storing passwords, coupled with the fact that Cloudron is open source, allows for bad actors to easily discover the algorithm used to hash passwords for Cloudron users (and admins alike), know the main login root url in many cases (my.example.com; must be on the 'my' subdomain) and, at the very least, the minimum & maximum password lengths plus accepted characters.
Perusing through Cloudron's code, I decided to seek out more information about how passwords are stored. This is of particular importance to me since I have certain applications that are mission critical for my users (i.e., mail / openvpn / chat clients / etc.), and most of these apps (e-mail included), are integrated with the LDAP - so the logins are uniform for nearly all.
Cloudron's Current Password Hash Algorithm
(please correct me if I am misinformed / misguided here in my assumptions)
I looked under the 'source code' section for Cloudron (underneath 'box').
Here is the link to the relevant code: https://git.cloudron.io/cloudron/box/-/blob/master/src/users.js
Specifically, I want to key on the defined variables below:
If the quality isn't that great, the relevant lines of code can be found between lines 70-73.
Specifically, those lines contain the commands:
var CRYPTO_SALT_SIZE = 64; // 512-bit salt var CRYPTO_ITERATIONS = 10000; // iterations var CRYPTO_KEY_LENGTH = 512; // bits var CRYPTO_DIGEST = **'sha1'** ; // used to be the default in node 4.1.1 cannot change since it will affect existing db records
Strong Issues That I Have With the PBKDF Used:
Salt: I don't really have any issues that we should dig into here. The salt is of a sufficient length & the 'crypto.randombytes' function is applied to the salt in order to generate a randomly different one for each stored password (although I'm curious as to what is used to create the 'randomness') ; not a big deal
Iterations: The iterations listed in the file (10,000) is nowhere near sufficient to offset the inherent weakness of the digest being used here. As shown in this link here (https://www.sjoerdlangkemper.nl/2016/05/25/iterative-password-hashing/) ; 10,000 iterations would impose almost no burden, computationally for a would-be attacker for the SHA-1 digest. In fact, the benefit from implementing 10,000 iterations is nominal, at best.
Crypto Key Length: In light of the super low number of iterations ran by the PBKDF function, coupled with the crypto digest itself, this bit length is merely aesthetic (its the block size for the algorithm). SHA-1's strength, theoretically is 160-bits.
Which means that only 80 rounds are required to break sha-1 (and this threshold has been met many times over).
4. Crypto Digest: 'sha-1' <-- the main problem here is that this hash algorithm is already broken and compromised. As seen in the link from the Google Researchers above, a complete collision was found in 2017.
A) Researchers were able to feasibly create a quasi-collision in 2015 using equipment that required no more resources than a $2,000 GPU VPS rented from Amazon (EC2) [source = https://sites.google.com/site/itstheshappening/]
B) Back in 2006, the NIST declared that sha-1 to be deprecated and completely removed from use by all relevant government agencies by 2010 (over a decade ago) = https://csrc.nist.gov/projects/hash-functions/nist-policy-on-hash-functions
In specific, they stated:
Federal agencies should stop using SHA-1 for generating digital signatures, generating time stamps and for other applications that require collision resistance.
C) This recent publication by Bruce Schneier (renown cryptographer), posted in 2020, shows the exponentially increasing ease with which sha-1 hashes can be collided (source = https://www.schneier.com/blog/archives/2020/01/new_sha-1_attac.html
Moral of the Story
sha-1 is insecure. No way around it.
Typically, this is something that one would consider to be a 'vulnerability' or 'exploit' that arises to the level of confidential disclosure, but I've already attempted to do so through the more personal chat channels ran by Cloudron (specifically on chat.cloudron.io), and it seems like my concerns were more or less put to the side (for whatever reason).
Therefore, I've decided to at least make sure that other Cloudron users & sysadmins are aware so that they can either:
- Assist me in echoing the cry for a near-immediate swap & upgrade in the password hash algorithm used.
- At least have proper knowledge of the inherent risk that their information (as well as that of their users) is currently in.
To be clear, I have faith in the Cloudron team that, given this blog post, they will take action quickly - and without delay - especially when considering that this post will now outline the solution.
Replacement Hash Algorithm Proposal - Argon2id
Reasons for Proposing Argon2id:
- It has been approved by php for inclusion in their packaged software, starting at version 7.3 and above (link = https://wiki.php.net/rfc/argon2_password_hash_enhancements) ; of note is the fact that this change was stamped via a php RFC (which the link above points to).
- It is the winner of the most recent, 'Password Hashing Competition' (PHC) [link = https://password-hashing.net/] ; for those unfamiliar with this competition, please do not be skeptical. I know that the title may seem a bit ... obtuse, especially when considering the actual prestige associated with being declared winner, but despite the unconventional name, winning this competition is something that garners international recognition & respect. Ironically, one of the motivations for the creation of the competition was to find a suitable, strong replacement for vulnerable, popularly used hash algorithms, like sha-1. (more information on the competition can be found here: https://password-hashing.net/)
- The use of Argon2 is on the precipice of being standardized by the IETF as an RFC (link = https://datatracker.ietf.org/doc/draft-irtf-cfrg-argon2/) ; it is currently on its 10th revision. Consensus has already been reached and there are already several (noted) Linux implementations.
Brief Rundown on How Argon2id Works
You may have noticed me use 'argon2id' interchangeably with 'argon2'.
To be clear, there are three different iterations of 'Argon2', which are:
A) Argon2i: Generates passwords in a memory-independent manner for the purposes of maximizing resistance to side-channel attacks.
B) Argon2d: Designed to minimize 'acceleration' attempts (i.e., through the use of GPUs / FPGAs / etc.)
C) Argon2id: Best of both worlds and the preferred / recommended iteration of Argon2
"But What About SHA-256 / SHA512?"
Those are great hash algorithms as well - but not for password-based purposes.
Unlike Argon2id, the SHA-hash family was designed in a way where hardware / software can be optimized to perform the respective hash operations at scale and speed for quicker authentication & verification purposes (also to ensure quick hashing of various items / inputs).
The best real world example we have of this is the SHA-256 algorithm as deployed in "Bitcoin".
Various 'ASIC chips' have been created, with pre-programmed circuits in the devices that are purposefully tuned to ensure that one can hash the SHA-256 algorithm at an optimal speed.
In May (2020), a new 'miner' will be releasing called the, "S19 Pro" by a company called, 'Bitmain'.
Per the specifications on its website, this device is allegedly capable of churning 110 TH/s, out-of-the-box (link = https://www.asicminervalue.com/miners/bitmain/antminer-s19-pro-110th).
For further reference:
TH = 'terrahashes' per second
^ In order to assess the magnitude of 110 TH/s, it is useful to first gather an understanding of how many hashes are needed to amount to one "Terrahash".
Below is a conversion table:
Based on our reference table, 1 TH = 1,000,000,000,000 hashes per second (on the SHA-256 algorithm, specifically).
At 110 TH/s, that number then turns into 110,000,000,000,000 hash operations per second that can be performed by the device we linked above (S19 Pro).
How Much is This S19 Pro?
Pre-order sales peg it at around $3,000/unit.
Yeah, that's it.
And its worth considering the fact that there are plenty of entities that have entire warehouses full of devices with this type of capability.
So, should we really be gambling on sha-256 / 512 in a world where potentially antagonistic hardware like the miner described above exists?
What About 'ASIC Miners for Argon2id'?
Here's the awesome part - there are none.
Since Argon2id is designed to be memory intensive in a way that results in exponentially more computer resources being used to 'brute force' a result as the algorithm increases the data used / complexity / iterations, 'accelerating' the hashing of this function is virtually impossible.
(on a more technical level: 'parallelization' does not increase efficiency here)
How Easy Would Replacing 'sha-1' With Argon2id Be?
There are already Argon2 iterations in:
A) NodeJS = https://www.npmjs.com/package/argon2
C) php = https://www.php.net/manual/en/function.password-hash.php
D) Golang = https://www.alexedwards.net/blog/how-to-hash-and-verify-passwords-with-argon2-in-go
E) python = https://pypi.org/project/argon2/
Net Result: Security Increased EXPONENTIALLY
That word 'exponentially' is not being used in a casual sense - but rather literally, in a mathematical, numerical-based sense.
This change extracts all Cloudron users (prior & present) from the murky waters of an already-compromised password hash signature to a modern, newly accepted standard, that has received a seal of approval from virtually every relevant, independent body of cryptography / cryptanalysis / security.