Major components of popular high level web stacks have had bugs of this severity lurking in them for years.
Edit: Done, thanks.
The specific exploitable condition is indeed the recurrence of a specific nonce/counter tuple; the point is, there are systems in which attackers can induce that condition, as opposed to simply having the system blunder into it (for instance, by using the same nonce every time).
In particular FormsAuthenticationTicket, and FormsAuthentication.Encrypt()
ASP.NET Forms are a pretty good textbook case study of why you should never build unnecessary crypto into your system. Microsoft spends millions every year on external security validation and also keeps a highly regarded team of crypto designers on staff. Still missed the most blatant web crypto flaw of 2010.
Don't encrypt reset tokens. Send random strings.
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.)
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.
I'm being sarcastic if it wasn't obvious.
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 , 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  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?
However, because you're typically doing a password reset in a centralized database anyway, there's not really much point.
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."
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).
This sounds interesting, and completely counter to my understanding of how compression works.. I thought CRIME's innovation was to exploit compression ratios as a proxy for cleartext. Poking a compressor into emitting probabilistically assigned bit-aligned symbols that happen to correspond to its input seems unlikely.
With careful control over the data, you could make it so no dictionary lookup would ever succeed. This would mean no strings would ever be eliminated through backreferences.
Most also have a minimum match length, making your life a bit easier here.
Most also are outputting encoded streams that basically a little decompression VM (IE literal, 0, backreference, 255 bytes ago, size 30). Because of this, they will not eliminate duplicates where the match is too small (only 2 bytes).
This will get you past the duplicate elimination phase, but not the huffman phase.
Getting past the huffman phase is harder.
To get it to output a stored block, you have to convince it the raw literal length of the block will end up less than the length of the block as encoded.
For zlib, we have
opt_len = (sizeof (compressed data in bits) + sizeof (huffman tree in bits ) + 3 + 7) / 8
if (stored_len+4 <= opt_lenb) use stored block
So you do have some chance to beat it by messing with the probability distributions, and do get a little leeway.
On the plus side, you only need to mess with the probability for a single zlib block, not the whole shebang.
Why would a site use blobs for reporting?
You cant replay attack the reset link once its used, it expires in 24 hours and so long as the 'secretkey' was sufficiently unique, you wouldnt be able to bruteforce or crack it.
All the php script needs to do is attempt to build a 'good' md5 hash and see if they match- if they do, let you input a new password to store.
Just use a random string as a primary key for a token table in a database and be done with it.
Edit: And you're as exceptional as Daeken. I'm a builder, not a breaker. I'm awful at security beyond knowing better than to do anything but a random token + short lifetime.