With reference to some security paper I read, I found out that a cookie with the secure flag set can only be sent by the client over connections that are using HTTPS, not HTTP, but the cookie itself can be set from the server with a secure flag from an insecure HTTP connection. Why is it allowed?
Secure cookies can be set over insecure channels (e.g. HTTP) as per section 18.104.22.168 of RFC 6265. It explicitly mentions that the Secure flag only provides confidentiality and not integrity, as a Secure flagged cookie can still be set from an insecure channel, overwriting any previously set value (via a secure channel or otherwise):
The Secure attribute limits the scope of the cookie to "secure" channels (where "secure" is defined by the user agent). When a cookie has the Secure attribute, the user agent will include the cookie in an HTTP request only if the request is transmitted over a secure channel (typically HTTP over Transport Layer Security (TLS) [RFC2818]).
Although seemingly useful for protecting cookies from active network attackers, the Secure attribute protects only the cookie's confidentiality. An active network attacker can overwrite Secure cookies from an insecure channel, disrupting their integrity (see Section 8.6 for more details).
Section 8.6 gives several examples, but I won't copy-paste them here due to how long the section is.
As for why, there's no clear use-case that I'm aware of. I suspect that the RFC was written from the perspective of having only the goal of protecting confidentiality, and therefore preventing Secure flagged cookies from being accepted when set over HTTP was an unnecessary restriction for that goal. My guess would be that the rationale was "if we provide this functionality, people may assume that cookie integrity is protected by the Secure flag, and we don't want people to make that assumption".
That said, the fact that the data can be set over an insecure channel does somewhat negate the concept of only sending the cookie value over a secure channel, so the decision's sensibility is arguable. The RFC does at least mention that you lose confidentiality if you do this.
OPTIONAL. The Secure attribute (with no value) directs the user agent to use only (unspecified) secure means to contact the origin server whenever it sends back this cookie, to protect the confidentially and authenticity of the information in the cookie.
The user agent (possibly with user interaction) MAY determine what level of security it considers appropriate for "secure" cookies. The Secure attribute should be considered security advice from the server to the user agent, indicating that it is in the session's interest to protect the cookie contents. When it sends a "secure" cookie back to a server, the user agent SHOULD use no less than the same level of security as was used when it received the cookie from the server.
My interpretation is that they wanted the server to take care of security on the way to the client and have a way to tell the client it should do the same.
Indeed the result is dubious as mentioned in Polynomial's answer.
Currently on the web we have to accept that many browsers and their users will usually attempt to access web resources over unsecured (HTTP) connections.
As such there is some slack in the RFC with regards to when cookies with the Secure cookie flag can be set. Specifically, yes, it's permitted to set cookies with the Secure flag even if you are doing so over an HTTP connection.
The Secure flag can only server to augment security, so there's no reason to prevent this from working from a technical or security point of view, although this is not to say it's a good idea to do this. From an efficiency point of view, it might be reasonable to respond to login requests with the necessary authentication information (in a cookie with the Secure flag) and then redirect the user to HTTPS where the new authentication cookie will actually be sent.
At this point it's possible that HSTS headers have been sent, too, so the browser will not try to use HTTP again in the future, thus mitigating future cookie overwrite attacks.
Now you'd be right in thinking that at this point an attacker could have intercepted that initial cookie data and hence use that to impersonate the user. This is less than ideal. But so is depending on the user connecting to the site over HTTP and receiving an HSTS header without an attacker tampering/stripping this header. That's why we have HSTS pre-loading. To this end, cookie secure flag pre-loading might be an interesting concept!
It can be assumed that after setting the cookie, the only risk to the user in terms of network attacks is that the browser has no HSTS instructions for the domain in question. Then an attacker forces the user to deauthenticate (perhaps by blocking SSL traffic, and waiting for the user to attempt typing in the address anew where it will most likely initiate an HTTP connection), intercepts the authentication credentials and/or token, removes the secure flag and ensures an HTTPS redirect doesn't occur for the client (whilst potentially negotiating that to the server if necessary).
This may be helpful for security in certain situations, basically if your internet connection was tampered due to lack of HTTPS encryption. However in most relevant cases cookie injection is low on the list of concerns compared to the other compromised features.
The HTTP protocol does not currently offer a way for the client to provide metadata about the cookie.
For example, if a cookie is set with
path=/, and later a cookie is set with
path=/narrow-scope Then if you visit the site, visiting a
/narrow-scope URL, both cookies are sent:
Cookie: name=valueA, name=valueB.
The server cannot tell what specific path was used for each cookie. Only that the metadata between them is different otherwise they would be considered the same cookie (having the same
Similarly, there is no way for Cookies to be marked as whether it the
Secure flag is set or
HttpOnly. No metadata is passed from the client to the server.
In order to prevent an HTTP page from setting a secure cookie would result in two possibilities:
All HTTP-provided cookies are not accessible when visiting the HTTPS page. This would be a significant break in compatibility.
Or Metadata is added to the Client-provided
This would be a big change, and there is not that much demand for it. Also in most cases it does not equal a security feature.
Ultimately the correct solution is to force users to use HTTPS connections.
The question of where in the RFC is this documented has been answered sufficiently.
As with other security features, this particular feature ("secure cookie") has one and only one goal: to avoid a bystander/sniffer to get your cookie.
It is not meant to be a panacea against all possible kinds of cookie attacks, but only this very specific attack:
- The browser presents some credentials to a server (via a secure connection).
- The server creates a session and hands over the cookie to you (via a secure connection).
- The browser send the session cookie back with further requests (via secure connections).
- An attacker somehow manages to make your browser do an insecure connection to the original server.
- The attacker sniffs the HTTP request and now has the cookie.
We can assume that 1., 2. and 3. are harder to attack then 4./5.
The user might be trained to check that a login form displays a HTTPS URL and a "green flag" next to the URL, depending on the browser. At the time when you enter your credentials, a wise user can reasonably be expected to pay attention to the URL, these days. (This is how the usual mail spam attack works, by fooling them to enter their username/pw at some arbitrary URL - a topic for another day.)
Is very hard to attack unless the server is buggy: the server knows perfectly well whether the connection is HTTP or HTTPS, so will only create a session if it comes over HTTPS. A really important system will better not listen on HTTP anyways.
The regular requests do not need to be attacked. They will go over a secure HTTPS connection and all will be fine.
Making a browser connect to arbitrary URLs is pretty easy - just place an tag somewhere or fire off some AJAX if you can. And some servers may offload static images and such to an insecure connection anyways to save CPU, so an attacker won't need to do anything at all.
So, this scenario is averted by the secure cookie. The cookie will only go over HTTPS, so the attacker can not sniff the cookie.
Note that it is hard to protect against 4. It is pretty easy to make a browser request any arbitrary URL. Note that you do not need to actually request a valid URL, you only need the browser to send the HTTP request (including the cookie); you don't care about the result, and it is impossible for the server to prevent the browser from sending the insecure request in the first place, except by not listening on HTTP at all, i.e., not having the TCP/IP port open. But even this is not enough; if the user goes through a proxy (common in corporate intranets), then the browser will still send the HTTP request to the proxy (over HTTP), and an attacker who sniffs between the browser and the proxy still has the cookie, even if the actual server never accepted the TCP/IP connection.
The "secure" cookie is meant to protect against a very specific problem which otherwise would be impossible to protect against.
It is not meant to secure against a buggy, lazy or misconfigured server which sends the cookie over an insecure channel in the first place.
Doing it like this (i.e., one feature against a specific attack) is a good thing, and it's what most security features do. You are expected to reason about what kinds of attacks a feature like this does not protect against; and this reasoning is rather easy because the scope of the feature is limited.