Duct Tape and Baling Wire–Cookie Prefixes

Update: Cookie Prefixes are supported by Chrome 49, Opera 36, and Firefox 50. Test page; no status from the Edge team. Another new cookie feature called SameSite Cookies is also under development by Chrome and Firefox; no status from Edge.


When I worked on Internet Explorer, we were severely constrained on development resources. While the team made a few major investments for each release (Protected Mode, Loosely-coupled IE, new layout engines, etc), there was a pretty high bar to get any additional feature work in. As a consequence, I very quickly learned to scope down any work I needed done to the bare minimum required to accomplish the job. In many cases, I wouldn’t even propose work if I wasn’t confident that I (a PM) could code it myself.

In many cases, that worked out pretty well; for instance, IE led the way in developing the X-Frame-Options clickjacking protection, not only because we found other approaches to be unworkable (bypassable, compat-breaking, or computationally infeasible) but also because a simple header (internally nicknamed “Don’t Frame Me, Bro”) was the only thing we could afford to build1.

In other cases, aiming for the bare minimum didn’t work out as well. The XDomainRequest object was a tiny bit too simple—for security reasons, we didn’t allow the caller to set the request’s Content-Type header. This proved to be a fatal limitation because it meant that many existing server frameworks (ASP, ASPNET, etc) would need to change in order to be able to properly parse a URLEncoded request body string.

One of the “little features” that lingered on my whiteboard for several years was a proposal called “Magic-Named Cookies.” The feature aimed to resolve one significant security shortcoming of cookies—namely, that a server has no way to know where a given cookie came from. This limitation relates to the fact that the attributes of a cookie (who set it, for what path, with what expiration time, etc) are sent to the client in the Set-Cookie header but these attributes are omitted when the Cookie header is sent back to the server. Coupled with cookies’ loose-scoping rules (where a cookie can be sent to both “parent” and “sub” domains, and cookies sent from a HTTP origin are sent to the HTTPS origin of the same hostname) this leads to a significant security bug, whereby an attacker can perform a “Cookie Fixation” attack by setting a cookie that will later be sent to (and potentially trusted by) a secure origin. These attacks still exist today, although various approaches (e.g. HSTS with includeSubdomains set) are proposed to mitigate it.

RFC2965 had attempted to resolve this but it never got any real adoption because it required a major change in the syntax of the Cookie header sent back to the server, and changing all of the clients and servers proved too high a bar.

My Magic-Named Cookies proposal aimed to address this using the “The simplest thing that could possibly work” approach. We’d reserve a cookie name prefix (I proposed $SEC-) that, if present, would indicate that a cookie had been set (or updated) over a HTTPS connection. The code change to the browser would be extremely simple: When setting or updating a cookie, if the name started with $SEC-, the operation would be aborted if the context wasn’t HTTPS. As a consequence, a server or page could have confidence that any cookie so named had been set by a page sent on a HTTPS connection.

While magic naming is “ugly” (no one likes magic strings), the proposal’s beauty is in its simplicity—it’d be a two line code change for the browser, and wouldn’t add even a single bitfield to the cookie database format. More importantly, web server platforms (ASP, ASPNET, etc) wouldn’t have to change a single line of code. Web Developers and frameworks could opt-in simply by naming their cookies with the prefix—no other code would need to be written. Crucially, the approach degrades gracefully (albeit unsecurely)—legacy clients without support for the restriction would simply ignore it and not enforce the restriction, leaving them no more (or less) safe than they were before.

Unfortunately, this idea never made it off my whiteboard while I was at Microsoft. Over the last few years, I’ve tweeted it at the Chrome team’s Mike West a few times when he mentions some of the other work he’s been doing on cookies, and on Wednesday I was delighted to see that he had whipped up an Internet Draft proposal named Cookie Prefixes. The draft elaborates on the original idea somewhat:

  • changing $SEC- to __SECURE-
  • requiring a __SECURE- cookie to have the secure attribute set
  • adding an __HOST- prefix to allow cookies to inform the server that they are host-locked

In Twitter discussion, some obvious questions arose (“how do I name a cookie to indicate both HTTPS-set and Origin locked?” and “is there a prefix I can use for first-party-only cookies”?) which lead to questions about whether the design is too simple. We could easily accommodate the additional functionality by making the proposal uglier—for instance, by adding a flags field after a prefix:

Set-Cookie: $RESTRICT_ofh_MyName= I+am+origin-locked+first+party+only+and+httponly; secure; httponly

Set-Cookie: $RESTRICT_s_MyName2= I+am+only+settable+by+HTTPS+without+other+restrictions

 

… but some reasonably wonder whether this is too ugly to even consider.

Cookies are an interesting beast—one of the messiest hacks of the early web, they’re too important to nuke from orbit, but too dangerous to leave alone. As such, they’re a wonderful engineering challenge, and I’m very excited to see the Chrome team probing to find improvements without breaking the world.

-Eric Lawrence

1 See Dan Kaminsky’s proposal to understand, given infinite resources, the sort of ClickJacking protection we might have tried building.

Duct Tape and Baling Wire–Cookie Prefixes

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s