4 ms·
Can anyone offer any insight as to why you wouldn't generate a one-time random string with a short lifetime for password reset emails? Sending a blob with data
by wooster 14y ago
Can anyone offer any insight as to why you wouldn't generate a one-time random string with a short lifetime for password reset emails? Sending a blob with data in it (encrypted or otherwise) seems like a potential information leak with no upside.
- daeken 14y agoFor forgot password, there really is no reason to take this approach, though if you do it sanely it's not a problem. The report generation and other things like that in their code, however, are reasonable to do this way if you do it right.
- tptacek 14y agoThat is exactly what you should do. The only upside to sending semantically meaningful data in email tokens is that parsing the responses doesn't require a central database lookup --- but that upside itself comes with the downside of losing the control that a simple database table gives you over outstanding tokens. And that's not really an "upside"; it's just a convenience. Don't encrypt reset tokens. Send random strings.
- danpat 14y agoYou can always achieve a token timeout by embedding a timestamp and signing the blob. However, because you're typically doing a password reset in a centralized database anyway, there's not really much point.
- alinajaf 14y ago> You can always achieve a token timeout by embedding a timestamp and signing the blob. What's the benefit of this over just sending a random string? One database read for the risk of an attacker being able to create arbitrary valid password reset tokens that never expire? That particular trade-off strikes me as fantastically bad, especially for an operation like password reset that doesn't happen very often. > However, because you're typically doing a password reset in a centralized database anyway, there's not really much point. Personally I find the incurred security risk more compelling than "we're hitting the database anyway, so who cares if we make another trip for the timeout."
- ars 14y agoYou have to be careful though. If someone managed an SQL injection and can read tables, but you are using bcrypt hash properly, you might think you are [somewhat] safe. (i.e. at least they can't write anything.) But if they can read the password reset tokens from your database they can login as any of the users. (This is especially bad if changing a password doesn't invalidate "keep me logged in" cookies.) The solution is to treat those tokens as passwords, and hash them as well. (I know this because I had to clean up after this exact senario happened to someone using Joomla. They got an admin login from a password reset token, from there they were able to write files to disk and fully take control of the server.)
- tptacek 14y agoIf you're writing injectable SQL queries, there is nothing I can tell you about crypto and password resets that can help you. Not all vulnerabilities are equally easy to blunder into. We can presume a competent development team will avoid SQL injection, or at least, will discover accidentally introduced SQLI quickly through testing. The same is not the case with crypto flaws.
- ars 14y agoIn that case why bother using bcrypt? After all your queries are perfect and no one can access the database. I'm being sarcastic if it wasn't obvious.
- tptacek 14y agoAnother way to think about it is: if you're using an SQL database at all, you've signed up for SQLI mitigation whether you use the database for reset tokens or not. However, you still have the option of not having to deal with crypto bugs.
- lvh 14y agoSo, I'm already sending random strings, but there's a few things that I know are just wrong and broken about my current thing, and I'm wondering what the appropriate way to fix it is. 1. It doesn't limit how many tokens you try to send out; I'm not entirely convinced this is an issue yet, since these tokens are 256 bit, so you'd have to create quite a few before random attempts would start working... 2. The tokens do not expire. Again, I know both of these are wrong, but I'm not sure what the appropriate way to deal with them is. Limiting [1], i.e. the number of outstanding tokens, sounds like a bad idea, because then an attacker could lock the legitimate user out from being able to reset their password (barring a support call). Doing statistics on how many password reset requests are being made, per host and per credential, seems more efficient. Adding a simple 24h lockout to [2] seems like a good idea, and it happens to be ridiculously simple to implement, too :) Oh, by the way: tptacek, I sent you an e-mail weeks ago about a Pycon talk -- did you happen to get it perchance?
- m_eiman 14y agoMost likely they wanted to use the same scheme everywhere in the webapp, and for some reason decided that encrypted data proxied through the user was the best choice. Assuming that the concept in general is sane, then it makes sense to not special case specific uses (less code where things can go wrong).