Live data from Hacker News

Okta Bcrypt incident lessons for designing better APIs

n0rdy.foo

131–140 of 169 posts

Re: Okta Bcrypt incident lessons for designing better APIs

#131

Earlier quoted context omitted.

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…

Password hash functions are designed to be slow, are designed to be use with salts, and may have low entropy inputs. Being slow is a waste for (true) KDFs, salts aren't relevant (although nonces may be), and are designed for high entropy inputs. The naming overlap between the two is bad, so the industry has tried to move towards naming the two differently. Password hashing functions are not ideal KDFs, even though a…

String KDFs are also slow. That's the basic strategy for making high-entropy keys out of low-entropy inputs.

Re: Okta Bcrypt incident lessons for designing better APIs

#132
post #47

I 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…

Something similar happens in my company too. In a particular place, we use the hash of a string as the key in a hashmap instead of the string itself, because the hash is smaller and is easier to compare after the initial map has been made. It is a 64bit hash too. I have been crying about this everytime it comes up, and the response is, it will never happen. My problem is that we will never know if it ever happens too…

This makes no sense - it’s a hash map because it hashes things for you…

Re: Okta Bcrypt incident lessons for designing better APIs

#133
I'm confused, it seems that the OP wants to use Bcrypt as an encoding/decoding utility.

About solutions, Django hashes by default the password only with a salt. I'm not sure why it would be valuable to combine user_id+username+password. I've always assumed that using salt+password was the best practice.

Re: Okta Bcrypt incident lessons for designing better APIs

#134
Another incident at Okta? Oh no! Its security has _always_ been a mess. It's a dumpster fire and no client of their cares because their identity systems are so messed up, that it's better to have the mess of Okta, than the mess they are sitting on. It's kinda crazy they get away with such incredibly bad security practices. Like... this bcrypt issue has been know for a LONG while. We used to test for it 8-10 years ago.

There's either (1) nobody competent enough there to know (which is likely not true, I had a pentester friend recently join, and she is very good), or, more likely (2) management doesn't care and/or doesn't give enough authority to IT security personnel.

As long as clients don't have any better options, Okta will stay this way.

Re: Okta Bcrypt incident lessons for designing better APIs

#135

I'm confused, it seems that the OP wants to use Bcrypt as an encoding/decoding utility. About solutions, Django hashes by default the password only with a salt. I'm not sure why it would be valuable to combine user_id+username+password. I've always assumed that using salt+password was the best practice.

Regarding the API design, I agree now with OP after reading other comments on HN. The API would be improved if it clearly indicates to the user when truncation is done, even if this understanding is implied by principle.

Re: Okta Bcrypt incident lessons for designing better APIs

#136
post #132

Earlier quoted context omitted.

Something similar happens in my company too. In a particular place, we use the hash of a string as the key in a hashmap instead of the string itself, because the hash is smaller and is easier to compare after the initial map has been made. It is a 64bit hash too. I have been crying about this everytime it comes up, and the response is, it will never happen. My problem is that we will never know if it ever happens too…

This makes no sense - it’s a hash map because it hashes things for you…

A hash map still stores the entire key, which may be undesirable if the key datum can be large.

Re: Okta Bcrypt incident lessons for designing better APIs

#137
post #130

Earlier quoted context omitted.

Yes, that's what I pointed out when you suggested there would be a problem with two different users having the same password.

I'm getting the feeling that there's some kind of miscommunication here. If only the password is used to generate the hash then that password, when used to match against a previously stored hash(cache key here), will also match it, thus producing the exact same vulnerability, but worse because it's enough to have the same password as someone else. Salting does not help here at all.

The whole point of salting is to avoid exactly that scenario, and, as I linked to, bcrypt requires salt.

So when you read "bcrypt(password)", that just means the salt is implicit, not that it isn't salted.

Re: Okta Bcrypt incident lessons for designing better APIs

#138

Earlier quoted context omitted.

BCrypt should loudly fail if more than 72 bytes are sent to its input.

Maybe it should. Discarding the rest of the bytes works fine for passwords , though. I guess that's just not sufficient.

In my book, discarding entropy is a generally dumb thing to do. Passwords are usually under 72 chars, but a lot of people use concatenations of usernames and passwords in their hash to get guaranteed domain separation between users.

Re: Okta Bcrypt incident lessons for designing better APIs

#139
I strongly agree with the conclusion that the libraries should reject input they can't correctly handle instead of silently truncating it.

I co-maintain a rate-limiting library that had some similar rough edges, where it wouldn't always be obvious that you were doing it wrong. (For example: limiting the IP of your reverse proxy rather than the end user, or the inverse: blindly accepting any X-Forwarded-For header, including those potentially set by a malicious user.) A couple years back, I spent some time adding in runtime checks that detect those kinds of issues and log a warning. Since then, we've had a significant reduction in the amount of not-a-bug reports and, I assume, significantly fewer users with incorrect configurations.

Re: Okta Bcrypt incident lessons for designing better APIs

#140
In Node, you would commonly reach for the builtin core "node:crypto" module to run cryptographic functionality like this. I wondered why that wasn't used here, but bcryptjs was. After digging into it a little, node doesn't ship with core support for bcrypt, because it's not supported by OpenSSL.

The node crypto module is essentially an API that offloads crypto work to OpenSSL. If we dig into OpenSSL, they won't support bcrypt. Bcrypt won't be supported by OpenSSL because of reasons to do with standardisation. https://github.com/openssl/openssl/issues/5323

Since bcrypt is not a "standardised" algorithm, it makes me wonder why Okta used it, at all?

I remember in uni studying cryptography for application development and even then, back in 2013, it was used and recommended, but not standardised. it says a lot that 12 years on it still hasn't been.

Post reply on HN