As I said in my previous article about cookie security, the current HTTP cookie specifications (Netscape cookies and RFC 2965) have a couple of serious security problems due to the way the server can specify the recipients of the cookie.
I've suggested two methods for dealing with the problem within the current cookie specifications, one using DNS lookups, which Opera is currently using, and the other requiring each TLD registry to post information about their domain structure.
Neither the TLD registries nor the DNS protocol people seem to want to use either of the proposals, basically because the proposals assigns "meaning to the content of labels and the position of labels" which they consider a mistake (apparently there are similar assumptions/problems in other proposals to the IETF, as well).
I certainly understand their reservations, but the abovementioned methods are the best I have been able to think of which that can control the existing problem without "breaking the Internet".
There is another option, however, which I considered mentioning as "Alternative 0" in my recent presentation of my proposals to the IETF DNS Operations Work Group, but it is a "break the Internet" proposal: Redefine how cookies are shared among servers, and disable the old versions, both Netscape and RFC 2965 cookies, in newer browsers (not necessarily at the same time).
So, how would a new cookie standard look?
For the most part I think it will look like the current RFC 2965 but with a few modifications:
- Remove the Domain attribute, and replace it with a SubDomain flag-attribute.
- Redefine the Path attribute so that the specified path must be a subpath of the default path of the URL setting the cookie.
- Add a $Origin attribute when sending cookies to the server, identifying the server setting the cookie
- Use the RFC 2965 request cookie attributes ($Domain, $Path) and $Origin for all cookies, also for Netscape cookies.
The current rules for the Domain cookie attribute are what have led to the problems I've described. The rules permit, with some restrictions, the server to specify any of its (grand)parent domains, implicitly assuming that the server's administrator is in control of that domain or permitted to send cookies to all servers in that domain. This is a dangerous assumption.
My suggestion is to remove the attribute completely, and only allow cookies to be set for one of two destinations: The server itself, or the subdomain (indicated by a Subdomain attribute) under the server, which has the same suffix as the name of the server. This means that server.example.com will be permitted to set cookies for itself, or to all servers x.server.example.com, but NOT to the domain example.com. This will restrict cookies to a domain where it is reasonable to assume the administrator has control, or is authorized to set cookies.
In a manner of speaking, this will make the server setting the cookie the main entrance of the site, with all content behind it.
The Path attribute has a similar interpretation as Domain: you can set a cookie for any parent path on your server (or domain), but not a subdirectory. Actually, the situation in Netscape cookies is a bit different, since Netscape never specifically said there was a path restriction when setting cookies, so the de-facto situation is that a server can set Netscape cookies (but not RFC 2965 cookies) for any path, without limitations. This is probably OK on a single-owner site, but not in shared hosting environment; The other website owners would not normally want to get somebody else's cookies.
My suggestion is that, if the abs-path of the URL setting the cookie is "/path/name", cookies should be limited to either the abs-path ("/path/name") portion of the URL setting the cookie, or to the default path ("/path/"), or to a path containg a prefix of "name" (e.g. "/path/na" or "/path/"+substring("name",x). As for domains, this will restrict cookies to an area of a website where it is reasonable to assume the administrator has control, or is authorized to set cookies.
When sending RFC 2965 cookies back to the server the client have to send along the Domain, Path and Port attributes that was used when the cookie was set. This was introduced to make the server able to distinguish which cookies it really wanted to use.
I suggest two changes to this format:
- This information should be sent with all cookies, also the old cookies, and the $Domain and $Path attributes should be sent even if they were not orginally defined (using the default values). This will make it possible for servers to verify that they are not getting cookies it should not receive.
- A $Origin attribute, specifying which server originally set the cookie. This attribute is not really necessary (and might perhaps be omitted) for cookies where the Subdomain attribute mentioned above is used, but will defintely be useful when handling
Netscape and RFC 2965 cookies. It could also help with debugging.
Another possibility I'm considering is whether or not there should be an upper limit for how long a cookie can be valid. There are lots of servers setting cookies valid for 10 to 30 years. Are such long-lived cookies really necessary? Should we put some restriction at one, two or five years, or some other number of years? At the very least, perhaps a new specification should make it clear that a client MAY enforce an upper time limit for how long a cookie can be valid.
I know many people, in particular Web designers, will react strongly to some, or all, of these proposals.
What I hope people will understand is that we have a potentially serious security and privacy problem within the current definition of how cookies are used, and that we should fix the problem.
Two of the possibilities are what I have proposed earlier, but those are, as a couple of commenters in the IETF DNSop Work Group put it, "kludges" and "hacks".
Another possibility is to make cookies safe (or safer) by default. That will, however, require a rewrite of the rules and deprecation of the old-style cookies, as suggested above.
Websites implemented according to the prposed definition above are, fortunately, compatible with the old system. During the transition to the new cookies, both types of cookies can be used.
What we need now are more suggestions for how to secure cookies. My suggestions are the best I have been able to think of. Perhaps somebody else can propose better solutions, with lesser impact on existing systems than my proposals?
Interesting reading.If there’s an effort to make cookies more secure, I do not recommend just “patching” the current behaviour. I believe there’s a need for a new and better approach, which should work alongside the current one until servers and pages which use the current cookies protocol will be rare. This will take time, but it’s better.There could be a protocol for cookies across multiple domains, of course with finer control. Here’s in short one quick idea:1. Allow any domain/path read and write from any domain/path. Practically no limits.2. When a server sets a cookie, it can use wild cards: Set-Cookie-Domain: *.affiliate.com/*. Or … it can be specific: sub.example.com/page.3. Each page served must specify within an HTTP header from which other servers and paths it does accept cookies from. Thus, example.com can set it accepts cookies only from *.example.com/* and from affiliate.com/*.4. There must be a maximum life time limit, as you suggested.5. Bigger cookies should be allowed. At least 1 Megabyte of cookie data.This opens-up the possibility for cross-domain and cross-site attacks, however it puts the security problem in server owner hands. Meaning, if I configure my server to accept cookies set to my domain from any other domain, it’s my problem, it’s not the user agent, nor the user.Lets say I go to example.com which sets a cookie for affiliate.com, and affiliate.com is configured to accept cookies set by example.com. Now, the first request I do for affiliate.com won’t contain the cookie, because my UA does not know affiliate.com accepts cookies from example.com. Thus, there’s a delay. There could be a “one-time-per-session pre-request” specifically for checking Cookies-accept-from, however, this delay might prove to be actually “good” against possible attacks (?).Would this be too liberal?
Personally, I think it is much too liberal. Sorry.One of the aspects of cookies that have caused the most concern over the last 10+ years is cross-site sharing of information.The problem with having servers tell the client the sources of the the cookies it is willing to accept is, as I told “Aux” in my previous cookie article, that you have to make at least one extra request to the server to find out, before sending the actual request. This will slow down loading, in particular if it has to be done for each resource, and create an incentive for just sending the cookies anyway (not that I expect that to happen without a bugtraq posting followed by rapid retreat by the vendor, but it will still be a temptation).About increasing cookie size: I get enough complaints from cellphone vendors about our current limit of 4 KB, and a maximum of 300 cookies on devices, thank you. They would scream, loudly, about a possible megabyte size for cookies.A large size cookie will also take a long time to transfer to the server even over a broadband connection, and using such cookies could be prohibitively expensive for the website: If a site has a 10 Gbs connection, it could only serve ~1200 requests every second, assuming just one megabyte cookie, and the traffic load could reach 100 TB a day. Just sending the request would most likely take 10-30 seconds, much more if there are several such cookies. (Just consider that when Opera 6 had a 512+ byte charset header people complained loudly about it).The idea about cookies is, as stated in the name of RFC 2965, “State Management”, not “State Storage”. The server(s) are supposed to keep the actual data of the state, while the client only provides the identifier that the server can use to access the state.There is another reason to keep the state storage serverside: Security. Information stored client side can easily be read and manipulated, unless draconian encryption measures are used to protect the data.In fact, I think there are very few purposes that (actually) requires the current maximum length of 4KB (at least that is what Opera uses) for the entire cookie specification including domain, path, etc. Those purposes are usually subscription lists or some kinds of configuration data, which could easily be stored serverside. Perhaps it would be an idea to introduce a maximum combined name and value length of, say, 256 or 512 bytes?When (or if) my suggestions get off the ground and are presented in an IETF Internet Draft, there will most likely be a lot of discussion, and I suggest that you present your suggestions to the IETF HTTP Work Group (which is waking up after being dormant for several years) at that time. You may also submit your own proposals to the IETF as an Internet Draft.What goes into a hypothetical new Cookie Standard will ultimately be decided by a rough consensus of the IETF participants, in particular the members of the HTTP WG discussion. Anyone can participate in such discussions, either in the mailing lists or at the IETF meetings.
Thanks for your answer. This enlightens me in regards to several things.For cookie storage, you are right when it comes to server-side web pages. However, the problem cannot be avoided when developing “stand-alone client-side JavaScripts”. More specifically, with the advent of UserJS in Opera one has to save everything in the cookies (no userjs-specific storage currently). This is a problem.Storing sensitive data (except an ID and related data) is a huge mistake made by some developers.I don’t currently have any strong opinions in regards to a new Cookie Standard. I will probably subscribe on the mailing list (at least as a reader), when the time comes.
Robodesign, you’ve heard the saying about the hammer and the nails, haven’t you?If you think about it, I’ve no doubt you will realize that cookies are not really suitable for persistent storage for User Javascript (or widgets for that matter), if for no other reason that that using cookies would caused them to be sent to the server.IIRC Widgets already have a persistent storage system separate from cookies. Perhaps something similar can be created for UserJS, if it is needed?
http://www.whatwg.org/specs/web-apps/current-work/#scs-client-side
Yngve: That’s something I have asked for from day 1 of UserJS :). We need persistent storage system separate from cookies, just like in Widgets. Until then, web developers have to cope with the missing feature.Zbraniecki: I know of that, thanks. Is it implemented in Opera 9? Maybe I missed it in the change logs.
Thank you, very nice!