Seems like credentials being stored in logs is something that happens at pretty much every tech company - see e.g. Facebook[1] and Google[2]. Perhaps client and serverside hashing should be standard - at least then the actual credentials wouldn't be leaked, and the salt could be rolled the next time the user inputted it
Rather than this workaround, don't use secrets this way at all. Do public key crypto. You don't need a PKI because you have an existing registration + authentication flow you can re-use to figure out which keys belong to which users.
This design is safe because your systems don't have any secrets to mistakenly log or otherwise lose. Make things we don't want to happen _impossible_ and they'll stop happening. Merely saying "Don't do that" doesn't make it stop happening.
Your site can literally post all the WebAuthn registration data for users on the front page, and it won't make it any easier for bad guys to sign in as those users, there aren't any secrets in there. That's a correct design.
PIN's are 4 digits in the UK. Hashing them (even with a per user salt) would only produce 10k possible hashes. To have anything that was difficult to brute force would also just not practical on CPU constrained mobile devices.
When traditional banks do "1st, 2nd and 4th character" checks (i.e. via their apps), some go to pretty good lengths to protect these, even given the limited entropy.
These systems are typically backed by HSMs, and the HSM generates a high-entropy "challenge". The challenge is sent to the client, which combines the challenge with the characters the user entered. The resulting hash is sent back to the HSM, which can verify internally that the correct characters were selected, by computing the expected hash for the correct response (hopefully in constant-time).
It seems there is a bigger issue here -- Monzo used card PINs as a generic security credential in their app, and was storing them in a recoverable form (albeit only accessible to a very small number of staff). That's not standard practice elsewhere that I'm aware of - given use of the PIN is the "proof" you approved the transaction, it's usually used only in environments with dedicated PIN entry devices (ATM, card readers), rather than commodity devices (phones), unless those go through PCI-style verification and approval.
That's why you don't hash it, you encrypt it. What they want to do here can be solved using something called channel binding.
The problem is not that we can't do this securely, it's two separate but related problems:
1. The web stack was never designed for RPC and attempts to use it that way are often unsafe.
2. Poor or missing libraries to make common patterns safe. Why was the logging framework happy to log the PIN, well, because the type system didn't know the PIN is sensitive. Why was the PIN even sent in the clear at all, well, because libraries to do this securely aren't well known and the web doesn't help.
Comments
Seems like credentials being stored in logs is something that happens at pretty much every tech company - see e.g. Facebook[1] and Google[2]. Perhaps client and serverside hashing should be standard - at least then the actual credentials wouldn't be leaked, and the salt could be rolled the next time the user inputted it
[1] https://krebsonsecurity.com/2019/03/facebook-stored-hundreds...
[2] https://www.theverge.com/2019/5/21/18634842/google-passwords...
Rather than this workaround, don't use secrets this way at all. Do public key crypto. You don't need a PKI because you have an existing registration + authentication flow you can re-use to figure out which keys belong to which users.
This design is safe because your systems don't have any secrets to mistakenly log or otherwise lose. Make things we don't want to happen _impossible_ and they'll stop happening. Merely saying "Don't do that" doesn't make it stop happening.
Your site can literally post all the WebAuthn registration data for users on the front page, and it won't make it any easier for bad guys to sign in as those users, there aren't any secrets in there. That's a correct design.
PIN's are 4 digits in the UK. Hashing them (even with a per user salt) would only produce 10k possible hashes. To have anything that was difficult to brute force would also just not practical on CPU constrained mobile devices.
When traditional banks do "1st, 2nd and 4th character" checks (i.e. via their apps), some go to pretty good lengths to protect these, even given the limited entropy.
These systems are typically backed by HSMs, and the HSM generates a high-entropy "challenge". The challenge is sent to the client, which combines the challenge with the characters the user entered. The resulting hash is sent back to the HSM, which can verify internally that the correct characters were selected, by computing the expected hash for the correct response (hopefully in constant-time).
It seems there is a bigger issue here -- Monzo used card PINs as a generic security credential in their app, and was storing them in a recoverable form (albeit only accessible to a very small number of staff). That's not standard practice elsewhere that I'm aware of - given use of the PIN is the "proof" you approved the transaction, it's usually used only in environments with dedicated PIN entry devices (ATM, card readers), rather than commodity devices (phones), unless those go through PCI-style verification and approval.
That's why you don't hash it, you encrypt it. What they want to do here can be solved using something called channel binding.
The problem is not that we can't do this securely, it's two separate but related problems:
1. The web stack was never designed for RPC and attempts to use it that way are often unsafe.
2. Poor or missing libraries to make common patterns safe. Why was the logging framework happy to log the PIN, well, because the type system didn't know the PIN is sensitive. Why was the PIN even sent in the clear at all, well, because libraries to do this securely aren't well known and the web doesn't help.
PINS for the ATM are but my online banking has a number more
I assume they're all double-checking after it was reported by Facebook, and they're realising they've been doing the same thing for a long time too.