[philiptellis] /bb|[^b]{2}/
Never stop Grokking


Showing posts with label passwords. Show all posts
Showing posts with label passwords. Show all posts

Monday, March 17, 2025

On Migrating Character Encodings

Several discussions I've had with friends and colleagues recently reminded me of an incident we faced several years ago at Yahoo!

Now Yahoo! as a company was made up of many different local offices around the world, each responsible for content in their locale. Since there was a lot of user generated content, this meant users in a particular locale could easily enter content (blog posts, restaurant reviews, etc.) in their local language script.

Everyone was happy!

From about 2005 onwards, the company was looking to unify some of the platforms used around the world. For example, we had something like 4 or 5 different platforms to do ratings and reviews and it didn't make sense to have different architectures, database layouts, BCP setups, and a separate team managing each of these, so we started unifying. Building a common architecture was the easy part. I worked on several of these projects. Getting front end teams to migrate was also not terribly hard. Migrating content though, was tough because each region had content in their own locale and MySQL didn't let you set multiple character encodings on text columns.

So the i18n team started working with teams across Y! to move everything to utf8. The easy part was changing HTTP headers and <meta> tags. Content was a little harder, but doable with iconv(1) since in most cases we knew the source character encoding and the destination was always utf-8. In some cases we had to guess, but it generally worked...

...until at one point we also decided to do it for authentication.

One of the things that was localized was authentication, because it allowed users in, for example, South Korea, to use Hangul characters in their passwords. Usernames were always restricted to just alphanumeric characters and underscores (If I remember correctly).

Passwords are stored, as they should be, salted and hashed, so the character encoding of the database column was always us-ascii, which is compatible with utf-8, so no biggie..., except the input character encoding used by the browser was based on the HTTP headers or META tags of the page, and the transfer encoding was based on the enctype of the login FORM.

Prior to this move, these were all set to a character encoding that made sense locally, so Korea used EUC-KR and China used Big5, and so the hashed passwords used the byte sequences that resulted from treating the input as one of these encodings.

After the move, the user would still type in the same password, but when we converted them to bytes, we used utf-8, which resulted in a different byte sequence than the original encoding, so hashing this new sequence of bytes resulted in a different hash, and users could no longer log in. Well, only users that used non-ASCII characters in their passwords.

I forget what the actual fix was, but there were several options on the table. One was to revert the character encoding changes on the login page and to re-encode all passwords after a successful login. Another was to generate two hashes, one using utf-8 and another using the pre-migration character encoding for the region and to allow a success on either to go through.

Saturday, June 09, 2012

Password reset over HTTP -- Part 3

It's been a while since my last two posts on the topic. This time it's Groupon.

The password reset page is over HTTP:
groupon-forgot-password

The reset password email that you receive contains a link that looks like this:

http://groupon.com/users/password_reset/{token}?utm_source=password_reset \
    &utm_medium=email&sid={sid}&user={uid}&date={YYYYmmdd}

This link does a 301 to itself and then a 302 to a HTTPS version of itself.

The good thing is that your new password is sent over SSL. The bad thing is that your reset token is sent in clear text.

Update: This issue has been fixed by Groupon a couple of hours after reporting it.

Wednesday, January 25, 2012

Password reset over HTTP -- Part 2

So it looks like I've been forgetting a lot of my passwords recently. After yesterday's issue with delicious submitting passwords in the clear, today I have a problem with livemocha.com.

As before, their login page is properly secured, but the password reset page is over HTTP:

This is the password reset page:

livemocha - password reset over http

And this is the URL the passwords are POSTed to, in clear text:

livemocha - password reset submitted over http

They also include third party code on their page, in this case it's a flash object from userplane.com, google analytics, and some JavaScript from pbc.com (alias for paybycash.com)

I've gotten in touch with them via their online form. Let's hope they respond.

Tuesday, January 24, 2012

HTTPS for login but HTTP for password resets

I recently tried to log in to my delicious.com account, and realised that I'd forgotten my password, so went through the reset password flow. This is what I saw...
  1. The Sign-in page is over SSL, which is good:
    delicious login over ssl
  2. The Forgot password page, where you enter your username is also over HTTPS. Not strictly required, but good all the same:
    delicious - forgot password over HTTPS
  3. This sends you an email with a link to reset your password. This page is not over HTTPS:
    delicious - reset password page -- not over HTTPS
  4. And submitting this form also goes to a page that is not over HTTPS:
    delicious -- form submit over http

Now they put the login page on HTTPS, which shows that they want to protect the user's password from sniffing, but the password reset form, which also accepts the user's password, sends the password in clear text over HTTP. This isn't good. If you're going to protect passwords via SSL, do it everywhere. FWIW, the userid (but not the username) is also sent in this form.

Additionally, the password reset page contains JavaScript from google analytics and chartbeat. As I've written before, you shouldn't trust third party scripts. While you may choose to ignore this on most pages, pages that accept the user's credentials should be considered sacred. The user assumes that anything they enter on this page is available only to your servers. By including third party JavaScript, you're breaking that trust.

I've emailed violations@delicious.com with these details, and am awaiting a response.

Update 2012-01-25 21:08 UTC: As of this time, Delicious have fixed the core issue of the password reset page being on HTTP. Kudos to the team for acting quickly. The secondary issue of third party scripts on this page still remains, but that's a policy decision for them, and not me.

...===...