4 ms·
The problem is that it requires a particularly detailed way of thinking about strings, much like the popular IEEE 754 floating point number question. If the co
by LeifCarrotson 7y ago
The problem is that it requires a particularly detailed way of thinking about strings, much like the popular IEEE 754 floating point number question.
If the code were instead written:
username = request.post_params('username')
email = request.post_params('email_address')
user = get_user_by_name(username)
if emails_are_equal(email, user.email_address)
reset_password(user.id, email)
Most people would not feel compelled to use user.email_address in the call to reset_password, because they're guaranteed to be equal by the previous line! The vulnerability was introduced when the author of emails_are_equal() wrote it with conversion to uppercase of the whole thing, and failed to realize that this conversion can collide with Unicode domains. They may also have done things like normalize/remove optional.dots+suffixes@gmail.com, "quoted" or (commented) local parts. There's a lot of magic - and a lot of risk - in an emails_are_equal method.
- thaumasiotes 7y ago> There's a lot of magic - and a lot of risk - in an emails_are_equal method. My whole point is that changing reset_password(user.id, email) to reset_password(user.id, user.email_address) neutralizes that risk. Then it doesn't matter whether emails_are_equal is risky or not, because a failure in emails_are_equal can only cause you to do a safe thing. What's less embarrassing -- "we accidentally sent a password reset for your account to you", or "we accidentally sent a password reset for your account to someone else"? So you might not feel compelled to rewrite reset_password(user.id, email) as reset_password(user.id, user.email_address) -- but you should.
- nybble41 7y ago> They may also have done things like normalize/remove optional.dots+suffixes@gmail.com, "quoted" or (commented) local parts. At least the first two (removing dots and suffixes), along with conversion to lowercase, are strictly invalid transformations which may result in an email address referring to a different account. Sure, most email providers treat the account name as case-insensitive, and the use of '+' as a label/subaccount separator is a common convention, but neither of these is required. The RFCs say that the account name is case-sensitive (unlike the domain name) and '+' is just an ordinary part of the name; any special significance is assigned by the server. Ignoring '.' characters is something specific to Gmail. In the context of a search it's not unreasonable to ignore some of these differences, but at that point the matching names aren't "equal", just "similar". Certainly it should never be assumed that it's safe to send email to the transformed version of the address.