Hardened stateless session cookies

The root cause behind the last-but-one WordPress cookie debacle was that the authors invented their own password hashing and cookie generation scheme. This is generally a bad idea, since it’s hard even for experts to get these right. Instead, whenever possible, a well-studied proposal should be chosen. It is for this reason that I suggested the phpass library for password hashing, and the Fu et al. stateless session cookie proposal.

These choices would be a substantial improvement on the previous custom design (had they been implemented correctly), but I still was not quite satisfied. The Fu et al. scheme has the property that an attacker who can read the cryptographic key stored in the database can create spoofed cookies. Given the history of WordPress security, it seems likely that there will eventually be a vulnerability discovered which allows the key, which authenticates cookies, to be leaked.

It’s good practice in security engineering to design systems with the widest possible range of attacker capabilities in mind. I therefore designed a cookie scheme which would do all that the Fu et al. design did, but also maintained some of its security properties if the attacker has read-access to the authentication database and knows the cookie authentication key. I published a paper on this topic — Hardened stateless session cookies — at the 2008 Security Protocols Workshop.

The trick behind my scheme is to store the hash of the user’s password in the cookie, and the hash of that in the authentication database. This means that it’s possible for the server to verify cookies, but the authentication database doesn’t contain enough information to create a fake cookie. Thus an attacker with read-access to the database still needs to know the user’s password to log in, and that isn’t stored. There are some additional subtleties to resist different attacks, and those are described in the paper.

I hope this proposal will trigger discussion over this important problem and lead to improved cookie authentication schemes.

Why in gods name you want to save password hash in cookie?
Simply store session id in cookie, and tie session to ip and maybe some other uniq identifiers and invalidate session as soon as you detect some anomalie (ip change, etc). If attacker will have access to password hash database, he will still be forced to crack password in order to create valid session for himself.

There are a few differences between my approach and that of WordPress.

Firstly, I’ve described my scheme and the rationale in a paper at a peer-reviewed conference. This gives researchers an opportunity to find flaws and suggest improvements.

Secondly, I only started to develop my scheme after looking for existing proposals which gave the same security guarantees. In contrast, the WordPress system has far poorer security than the standard solutions.

Thirdly, I based my proposal on an existing scheme and was careful to avoid introducing new vulnerabilities. This significantly increases the chance that it is secure.

Someone has to design protocols, but only when necessary. WordPress invented their own because they either did not look at, or ignored, the existing literature. They also took the wrong approach in the design process. It’s therefore not surprising that their system was insecure.

I don’t store the full password hash in the cookie. Depending on the protocol variant, it’s either an encrypted version or the hash with salt removed. This means it’s not feasible to brute-force the password from the cookie.

The reason I store this in the cookie is that it’s something a server can verify but cannot create. You can only generate it with the password, which is not stored in the database and is discarded immediately after the password is checked and cookie generated.

I’ve described why session IDs are not desirable in Section 1.2 of the paper. The key problem is that the session table grows with the number of open sessions, not the number of users. This increases storage, makes load-balancing more difficult and creates additional vulnerabilities to DoS.

Thanks for the interesting proposal! Taking your advice seriously, one should not implement this oneself… so is an implementation with a liberal licence (e.g. BSD) available which is known to be free of bugs? 🙂

HTTP Digest Auth requires that the server either store the cleartext password or H(A1) = MD5(username . ‘:’ . realm . ‘:’ . password). Including the username and realm in the hash is better than nothing, but it’s not as secure as including a salt.

For example, it’s apparent when a user has changed their password back to an old value. Things may also go wrong if fields contain the “:” character.

Also, MD5 is applied only one time. This makes it easier to brute-force the password when compared to standard password hashing schemes built around an iterated hash.

It also suffers from the same problem as the Fu et al. paper, which my proposal tries to fix. Namely, if you get access to the authentication database, containing H(A1), you can spoof a HTTP Digest authentication response.

It at least used to be the case that Microsoft products (IIS and Internet Explorer) implemented a different and incompatible version of the HTTP Digest standard to Apache and Firefox. I don’t know if this has been fixed, but if not that effectively eliminates the usefulness.

From a usability perspective, there’s also the problem that the dialog box offered by browsers for Digest and Basic authentication is not customizable. This also reduces the attractiveness of these options when compared to HTML form password boxes.

Steven, could you please explain the purpose of iterated hashing of passwords in the proposed scheme? Maybe I’m missing something, but I see it only as a mean for DoS-attacking a server. If you’re worried of a possibility of brute-force attacks, they could be easily mitigated with programmed delays between login attempts (similar to unix login).

The iterated hashing is to increase the cost of a brute-force password discovery attack by someone who has obtained a copy of the password database. It is a standard component of password hashing schemes, for example Bcrypt.

Great read! I’m working on exactly this problem right now and really enjoyed your paper.

The MAC key seems like the weakest link in the system. Given the MAC key, any intercepted cookie can extended to work forever, and the only way to revoke it is to change the MAC key (which revokes all cookies), or for the user to change their password.

What if, instead of a global MAC key, there was a user specific MAC key (stored in the DB) that was rotated every time the user did a manual logout. That would invalidate all old cookies, and would allow for user at a time key rotation.

That would give better resistance, but would only allow one user session to be active at any time. I wanted to permit a user to be logged in from both home and work. If the MAC key was rotated, logging out of one would invalidate the cookie for the other session.

Steven, I really enjoyed reading this post and both papers. I just recently created a PHP class that handles this and linked your paper in the description so that people would understand the need as well as the reason for the PHP class.