Two weeks ago on this page, we reported on some Wordpress
vulnerabilities that were caused by incorrectly generating
authentication cookies. The article was a bit light on details about such
cookies, so this follow-up hopes to remedy that. In addition, Steven
Murdoch, who discovered both of the holes, recently presented
a paper on a new cookie technique that provides some additional
safeguards over other schemes.
HTTP is a stateless protocol which means that any application that wishes
to track multiple requests as a single session must provide its own way to
link those requests. This is typically done through cookies, which are
opaque blobs of data that are stored by browsers. Cookies are sent to the
browser as part of an HTTP response, usually after some kind of
authentication is successful. The browser associates the cookie with the
URL of the site so that it can send the cookie value back to the server on
each subsequent request.
Servers can then use the value as a key into some kind of persistent
storage so that all requests that contain that cookie value are treated as
belonging to a particular session. In particular, it represents that the
user associated with that session has correctly authenticated.
The cookie lasts until it expires or is
deleted by the user. When that happens, the user must re-authenticate to
get a new cookie which also starts a new session. Users find this annoying
if it happens too frequently, so expirations are often quite long.
If the user explicitly logs out of the application, any server-side
resources that are being used to store state information can be freed, but
that is often not the case. Users will generally just close their browser (or
tab) while still being logged in. It is also convenient for users to be
allowed multiple concurrent sessions, generally from multiple computers,
which will cause the number of sessions stored to be larger, perhaps much
larger, than the number of users.
Applications could restrict the number of sessions allowed by a user, or
ratchet the expiration value way down, but they typically do not for user
convenience. This allows for a potential denial of service when an
attacker creates so many sessions that the server runs out of persistent
storage. For this reason, stateless
session cookies [PDF] were created.
Stateless session cookies store all of the state information in the cookie
itself, so that the server need not keep anything in the database,
filesystem, or memory. The data in the cookie must be encoded in such a
way that they cannot be forged, otherwise attackers could create cookies
that allow them access they should not have. This is essentially where
Wordpress went wrong. By not implementing stateless session cookies
correctly, a valid cookie for one user could be
modified into a valid cookie for a different user.
A stateless session cookie has the state data and expiration "in the clear"
followed by a secure hash (SHA-256 for example) of those same values along
with a key known only by the server. When the server receives the cookie
value, it can calculate the hash and if it matches, proceed to use the
state information. Because the secret is not known, an attacker cannot
create their own cookies with values of their choosing.
The other side of that coin is that an attacker can create spoofed
cookies if they know the secret. Murdoch wanted to extend the concept such
that even getting access to the secret, through a SQL injection or other
web application flaw, would not feasibly allow an attacker to create a
spoofed cookie. The result is hardened
stateless session cookies [PDF].
The basic idea behind the scheme is to add an additional field to stateless
session cookies that corresponds to an authenticator generated when an
account is first set up. This authenticator is generated from the password
at account creation by iteratively
calculating the cryptographic hash of the password and a long salt
Salt is a random string—usually just a few characters long—that is added to a password before it gets hashed,
then stored with the password in the clear. It is used to eliminate the use of rainbow tables to crack
passwords. Hardened stateless session cookies use a 128-bit
salt value, then repeatedly calculate HASH(prev|salt), where
is the password the first time through and the hash value from the previous
calculation on each subsequent iteration.
The number of iterations is large, 256 for example, but not a secret. Once
that value is calculated, it is hashed one last time, without the salt, and
then stored in the user table as the authenticator. When the cookie value
is created after a successful authentication, only the output of the
iterative hash itself is placed in the cookie, not the authenticator that
is stored in the database. Cookie verification then must do the standard
stateless session cookie hash verification, to ensure that the values have
not been manipulated, then hash the value in the
cookie to verify against authenticator in the database.
If it sounds complicated, it is; the performance of doing 256 hashes is
also an issue, but it does protect against the secret key being lost.
Because an attacker cannot calculate a valid authenticator value to put
in the cookie (doing so would require breaking SHA-256), they cannot create
their own spoofed cookies.
While it is not clear that the overhead of all of these hash calculations
is warranted, it is an interesting extension to the stateless session
cookie scheme. In his paper, Murdoch mentions some variations that could be used to further
increase the security of the technique.
to post comments)