> was used to generate the cache key where we hash a combined string of userId + username + password. Don't conceive your own cryptographic hacks. Use existing KDF designed by professionals.
Okta Bcrypt incident lessons for designing better APIs
51–60 of 169 posts
Re: Okta Bcrypt incident lessons for designing better APIs
#52Reminds me of when I saw a junior developer calling SHA-1 on an incrementing integer ID, with no salt. We had a long talk about it, he thought it was too "scrambled" to allow anyone to recognize what was being done. He shouldn't have been so junior, he was 4 or 5 years into his career. I had to be the bad guy and override his decision without further discussing why it was a bad idea, and I really tried for a good 45…
Rainbow tables is not the (only) reason you dont want to hash something low entropy like an incrementing int, and adding a salt wouldn't make this secure. [Im assuming the usual definition of salt where it is known by the attacker... a pepper would be fine]
Re: Okta Bcrypt incident lessons for designing better APIs
#53Bcrypt is a password hash, not a KDF, which is the way it was used in this API. It's super unclear to me why they wanted a string-based KDF here at all; does anyone have more context? I've in the past been annoying about saying I think we should just call all password hashes "KDFs", but here's a really good illustration of why I was definitely wrong about that. A KDF is a generally-useful bit of cryptography joinery;…
So let me take on the burden of stupid here: how are a password hash and a string-based KDF different? (I mean, the oldest well-known example of the former literally calls itself a PBKDF.) I understand this particular function from strings to large fixed numbers was limited in the length of the string it would accept, and I agree that’s a problem, but it feels like a problem orthogonal to the distinction you’re drawi…
Re: Okta Bcrypt incident lessons for designing better APIs
#54That is such a rookie mistake. It's not some hidden information that bcrypt has a 72 char limit. Pretty widely documented in multiple implementations and languages. How does a company whose only job is security screw that up so badly?
On the other hand, I'm not a security developer at Okta.
Re: Okta Bcrypt incident lessons for designing better APIs
#55Earlier quoted context omitted.
HMAC-bcrypt is a more complicated version of the first construction I proposed, and it would need a rigorous cryptanalysis if someone wanted to actually use it in production. It sounds like Okta actually wanted PBKDF2(stuff) here. An authentication company should have known this...
I feel like the "authentication company should have known" thing is unuseful; most developers at "security" companies are just ordinary generalist developers. Ironically, I think they boned themselves by trying to be too clever here, not too casual.
Re: Okta Bcrypt incident lessons for designing better APIs
#56Also I'm not sure what functionality the authentication cache provides, but their use of bcrypt(userId + username + password) implies the password is kept around somewhere, which is not the best practice.
OT. Has Argon2 basically overtaken Bcrypt in password hashing in recent years?
Re: Okta Bcrypt incident lessons for designing better APIs
#57Re: Okta Bcrypt incident lessons for designing better APIs
#58> On the other hand, such long usernames are not very usual, which I agree with Weird take. Usernames are often chosen by the user. Less so in corporate world but definitely not unheard of
Re: Okta Bcrypt incident lessons for designing better APIs
#59I can see the incident was a jumping off point to talk about bad APIs (bcrypt probably should error >72) but it sounds like the actual bug was they weren't checking the value in the cache matched the data they used in the hash for the key. The authentication cache check should survive any arbitrarily bad hashing algorithm because all of them are going to have collisions (pigeonhole principal). Even an arbitrarily 'st…
Now, the data structure they're using for a cache will use some sort of hash table, likely in memory, so maybe they've got the 192-bit bcrypt "key" and then that's hashed again, perhaps well or perhaps badly [e.g. C++ really likes using the identity function so hash(12345) = 12345] but then a modulo function is applied to find the key in an index and then we go groping about to look for the Key + Value pair. That part the API probably took care of, so even if the hash has size 6-bits, the full 192-bit key was checked. But the original data (userid:username:password) is not compared, only that 192-bit cache key.
Re: Okta Bcrypt incident lessons for designing better APIs
#60Have they did a bcrypt(password + userId + username), it won't be so bad. Order of entropy is important. Also I'm not sure what functionality the authentication cache provides, but their use of bcrypt(userId + username + password) implies the password is kept around somewhere, which is not the best practice. OT. Has Argon2 basically overtaken Bcrypt in password hashing in recent years?
That depends on how exactly it was used. If it was simply used to check if previous authentication was successful (without the value containing information who it was successful for) then single long password could be used to authenticate as anyone.