Should a cookie with the host-only-flag replace a cookie without it? - http

RFC 6265 states that a user-agent should proceed in the following way when receiving a Set-Cookie header:
If the Domain attribute is set:
Set the cookie's domain to the domain-attribute.
Set the cookie's host-only-flag to false.
If the Domain attribute is not set:
Set the cookie's domain to the canonicalized request-host.
Set the cookie's host-only-flag to true.
This is all clear. The confusion comes with this paragraph:
If the user agent receives a new cookie with the same cookie-name,
domain-value, and path-value as a cookie that it has already stored,
the existing cookie is evicted and replaced with the new cookie.
Let's take an example, with two cookies received on the domain www.example.com:
Set-cookie: name=value
Set-Cookie: name=value; Domain=www.example.com
The domain (and path) will be the same for both cookies, but the first one will have the host-only-flag set to true, and the second one to false.
Reading the RFC, it looks like it doesn't matter when comparing the two cookies, and they should be considered equivalent anyway, but I'm not sure my interpretation is correct.
Should the user-agent replace the first cookie with the second one, or should it store both of them?

The paragraph that confuses you is about the ability to assign a new value to a cookie (as well as changing/refreshing the cookie expiration date). If it were not written that way, the HTTP client would need to store multiple cookies with the same name could and it would need to decide on another criterium which to send to the HTTP server upon the next request.
Regarding the second part of your question:
If those two cookies are specified within the same request, the second one "wins", therefore a cookie with the host-only-flag = false would be stored.
If those two cookies come in separate requests, the second one overwrites the first one, because they match in cookie-name (specified), domain-value (once specified, once derived), and path-value (derived). When storing them, the entries in the browser's cookie database only differ in the host-only-flag.
This host-only-flag comes into effect when the client issues a new request to the server (snippet from RFC6265):
The user agent MUST use an algorithm equivalent to the following
algorithm to compute the "cookie-string" from a cookie store and a
request-uri:
1. Let cookie-list be the set of cookies from the cookie store that
meets all of the following requirements:
* Either:
The cookie's host-only-flag is true and the canonicalized
request-host is identical to the cookie's domain.
Or:
The cookie's host-only-flag is false and the canonicalized
request-host domain-matches the cookie's domain.
The fine detail is in how the domain is compared. The matching algorithm is specified in section 5.1.3.
Essentially you can have a cookie be valid for all subdomains if the domain is specified with a leading "."
When the domain is omitted, though, (and therefore implied by the server from the request), this can never be the case because there always needs to be an identical match in the domain.
Further research determined:
In practice browsers store a domain that has been specified in the cookie with a prepended . (for www.example.com it will store .www.example.com) so that a request to subdomain.www.example.com will also return that cookie. When no domain is specified the plain domain without a prepended . will be stored, thus a request to a subdomain will not include that cookie.

Related

Why can't I see cookie parameters after I log in?

I'm working on making a Symfony website secure. I have taken a look at this page: How to set secure and httponly attributes on Symfony 4 session
and applied the suggested change into framework.yaml:
session:
handler_id: ~
cookie_secure: true
cookie_httponly: true
When I log in, in the network tab I see three instances of Set-Cookie. The first is a cookie removal, having secure and HttpOnly attributes. The second is a cookie creation, where the cookie identifier has the secure and HttpOnly attributes. The third is setting some parameters in an HTTP-encoded manner, this one also has the secure and HttpOnly attributes. So far so good. However, when I go to any page, I have a Cookie attribute among the Request Headers which has the same identifier as the one which was created earlier, but the secure and HttpOnly attributes are not specified.
So, when I log in and the cookie is created I have the attributes I expect, but later, on visiting separate pages I no longer see them. Why is the secure and HttpOnly attribute not specified on later, after-login Request Headers? Did I miss something?
The security attributes are set by the server in the Response headers and the browser uses them to determine if it has to send the cookie along in the Request, but it never sends the attributes themselves, just the cookie value. If you inspect an ajax or unsecure request the cookie header should not appear in the request at all.
You can see some examples in the RFC6265.

Are my cookies really HTTP only? Flag is absent in Cookie request header

Ive made some configurations to (finally) have my cookies set on HTTP only.
"Seem" to work.
Ive tried them with postman and I have the following:
When I hit the login page:
On the cookies section, my cookie with name JSESSIONID appears to be HTTP only (it has the check)
When I enter to the logged area , the same result...
The headers dont give me more details.
Then,
I check it with google chrome. I open the developers toolbar.
I load the login page.
At the headers on the response headers I get
Set-Cookie: JSESSIONID=434434..... HttpOnly
So, its fine (I guess).
Then I reload the page (or sign in).
Then the problem:
No response headers received.
The Request Headers brings my cookie (with the same ID at then the previous one) without the httponly, host info or any other cookie value I set before.
At the cookies tab I get Request Cookies only and no Response cookie.
And the request cookie is non http-only
At my resources tab, the Cookie is there, as HTTP only and with the previous values I set.
My question now is... Is it a really http-only cookie? Or my configuration is not properly set?
Should I always get the response cookie or the request cookie should be always http-only (In case I am trying to set it as http-only) or is this behavior normal (or at least accepted) ?
When I try to print my cookie with Javascript at both scenarios I get a null as response (what makes me think then it is correct).
Ideas?
Client doesn't send cookie attributes other than name and value back to server.
See also RFC6265 section 4.2.2 (emphasis mine).
4.2.2. Semantics
Each cookie-pair represents a cookie stored by the user agent. The
cookie-pair contains the cookie-name and cookie-value the user agent
received in the Set-Cookie header.
Notice that the cookie attributes are not returned. In particular,
the server cannot determine from the Cookie header alone when a
cookie will expire, for which hosts the cookie is valid, for which
paths the cookie is valid, or whether the cookie was set with the
Secure or HttpOnly attributes.
Everything's behaving as specified.

Domain set cookie for subdomain

I looked in many questions about cookies but I didn't find an answer on my problem. I have following scenario:
A user creates a login on example.com and should get a cookie but only for the subdomain fuu.example.com. I generate following HTTP header part:
Set-Cookie: name=TestUser; Domain=fuu.example.com; Path=/; secure; HttpOnly
But when I make a request to https://fuu.example.com, the cookie will be not added to the request. I wonder if it is possible that example.com sets a cookie for fuu.example.com. I know that it is possible that example.com set a cookie for .example.com also for all subdomains for example.com but that's not what I want.
How do I set a cookie for a subdomain? I am not seeing the cookie in a request to the subdomain.
No. Besides that fuu.example.com is an invalid Domain value (it must start with a ., i.e. .fuu.example.com) (see update below) the cookie would get rejected:
To prevent possible security or privacy violations, a user agent rejects a cookie (shall not store its information) if any of the following is true:
The request-host is a Fully-Qualifed Domain Name (not IP address) and has the form HD, where D is the value of the Domain attribute, and H is a string that contains one or more dots.
The request-host is example.com and the Domain attribute value is foo.example.com. But the request-host example.com does not has the form HD where D would be foo.example.com. Thus the cookie gets rejected.
Update    The current specification RFC 6265, that obsoleted RFC 2109 that is quoted above, does ignore the leading dot. But the effective domain is handled the same:
[…] if the value of the Domain attribute is
"example.com", the user agent will include the cookie in the Cookie
header when making HTTP requests to example.com, www.example.com, and
www.corp.example.com. (Note that a leading %x2E ("."), if present,
is ignored even though that character is not permitted, but a
trailing %x2E ("."), if present, will cause the user agent to ignore
the attribute.)
[…] the user agent will accept a cookie with a
Domain attribute of "example.com" or of "foo.example.com" from
foo.example.com, but the user agent will not accept a cookie with a
Domain attribute of "bar.example.com" or of "baz.foo.example.com".
The 2 domains example.com and foo.example.com can only share cookies if the domain is explicitly named in the Set-Cookie header. Otherwise, the scope of the cookie is restricted to the request host.
For instance, if you sent the following header from foo.example.com:
Set-Cookie: name=value
Then the cookie won't be sent for requests to example.com. However if you use the following, it will be usable on both domains:
Set-Cookie: name=value; domain=example.com
In RFC 2109, a domain without a leading dot meant that it could not be used on subdomains, and only a leading dot (.example.com) would allow it to be used across subdomains.
However, modern browsers respect the newer specification RFC 6265, and will ignore any leading dot, meaning you can use the cookie on subdomains as well as the top-level domain.
In summary, if you set a cookie like the second example above from example.com, it would be accessible by foo.example.com, and vice versa.
For more details : https://stackoverflow.com/a/23086139/5466401
Actually, there is a simple and fully cross-browser support way for sharing cookies between original domain and subdomains but you should share it in setting time, for comfortable working with cookie stuffs in browser I'm using js-cookie and with the below setting cookie it could be shared between original domain and all of its subdomains:
Cookie.set('key', 'value', { domain: '.domain.com' })
// a . added before domain name
Hint: Adding this . will share cookie with all sub-subdomain.

Reason to rename ASP.NET Session Cookie Name?

is there any reason (safety?) why someone should rename the ASP.NET Session Cookie Name or is it just a senseless option of ASP.NET?
If you have several applications running under the same domain on the same server, you may well want to have seperate session cookie names for each one, so that they aren't sharing the same session state or worse still overwriting each other.
See also the notes for the Forms Auth cookie name:
Specifies the HTTP cookie to use for authentication. If multiple applications are running on a single server and each application requires a unique cookie, you must configure the cookie name in each Web.config file for each application.
1) It might (slightly) slow someone down who is (casually) looking for it.
2) You might want to hide the fact that you are running ASP.NET
Below link provides more information about why session cookies should be renamed.
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet
"The name used by the session ID should not be extremely descriptive nor offer unnecessary details about the purpose and meaning of the ID.
The session ID names used by the most common web application development frameworks can be easily fingerprinted [0], such as PHPSESSID (PHP), JSESSIONID (J2EE), CFID & CFTOKEN (ColdFusion), ASP.NET_SessionId (ASP .NET), etc. Therefore, the session ID name can disclose the technologies and programming languages used by the web application.
It is recommended to change the default session ID name of the web development framework to a generic name, such as “id”."
With cookie prefixes, you can add a security attribute to your cookie by naming it a special way. So in that case renaming your ASP.NET session cookie does have an impact on security:
__Secure-… cookies can only be written from secure (HTTPS) sites.
__Host-… cookies can only be written from the same, secure domain. So not from subdomains or insecure (HTTP) sites.
According to the following specification, https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00, that modern browsers implement, the prefixes are used to make things more secure.
3.1. The "__Secure-" prefix
If a cookie's name begins with "__Secure-", the cookie MUST be:
Set with a "Secure" attribute
Set from a URI whose "scheme" is considered "secure" by the user
agent.
The following cookie would be rejected when set from any origin, as
the "Secure" flag is not set
Set-Cookie: __Secure-SID=12345; Domain=example.com
While the following would be accepted if set from a secure origin
(e.g. "https://example.com/"), and rejected otherwise:
Set-Cookie: __Secure-SID=12345; Secure; Domain=example.com
3.2. The "__Host-" prefix
If a cookie's name begins with "__Host-", the cookie MUST be:
Set with a "Secure" attribute
Set from a URI whose "scheme" is considered "secure" by the user
agent.
Sent only to the host which set the cookie. That is, a cookie
named "__Host-cookie1" set from "https://example.com" MUST NOT
contain a "Domain" attribute (and will therefore be sent only to
"example.com", and not to "subdomain.example.com").
Sent to every request for a host. That is, a cookie named
"__Host-cookie1" MUST contain a "Path" attribute with a value of
"/".
The following cookies would always be rejected:
Set-Cookie: __Host-SID=12345 Set-Cookie: __Host-SID=12345;
Secure Set-Cookie: __Host-SID=12345; Domain=example.com
Set-Cookie: __Host-SID=12345; Domain=example.com; Path=/
Set-Cookie: __Host-SID=12345; Secure; Domain=example.com; Path=/
I think its mainly a matter of taste. Some people/companies want control every aspect of their web apps and might just use another name for consistency with other cookie names. For example, if you use very short one-character parameter names throughout your app you might not like session cookie names like ASPSESSID.
Security reasons might apply but security through obscurity is rather weak in my opinion.

Is the cookie "metadata" (expires, path,...) transferred to the server?

When you set a cookie, you set the raw cookie data, and some metadata. This metadata includes the path for where the cookie is valid, the expiration time of the cookie, and so on.
When a browser performs a request, what exactly will the browsers send with it? Will it send the full cookie, with all the "metadata"? Or only the actual data of the cookie, without the metadata?
No only the value of the cookie is returned in subsequent requests, the other metadata stays on the client.
When you define a cookie on the server a Set-Cookie header is created in the response carrying the name, value and other metadata about the cookie. Multiple Cookies will create multiple Set-Cookie headers in the response.
When the browser makes subsequent requests it checks its "database" of available cookies to see which cookies are appropriate for the path being requested. It then creates a single Cookie header in the request that carries just a series of name/value pairs of the qualifying cookies.
Its important to keep tight control on the number of cookies and the size of the data otherwise you may find that the weight of cookie data being sent for each and every request can be deterimental to performance. This would be much worse if the metadata were returned with the cookies as well.
The server sets the cookie with the "Set-Cookie" header. This contains the metadata (path and expiry), if specified. The client (browser) only sends the cookie itself in a "Cookie" header.
Firebug is a useful tool for Firefox to view all these headers. Similar tools should be available for other browsers.
only the cookie data is sent to server,other metadata is for the browser to perform some actions like cookie expiration
the user-agent will re-transmit the path, domain, and port attributes if the cookie was set under RFC2965 (via the Set-Cookie2 header) and if the attribute was specified by the server. a sample request might contain:
Cookie: $Version="1";
name="val"; $Path="/site"; $Domain=".example.com"; $Port="81";
name="val"; $Path="/site/dir"; $Domain=".example.com"; $Port="81"
if the cookie was specified using the original netscape Set-Cookie header, no attributes will be re-transmitted. if multiple cookies with the same name (but different paths) are valid for the request, all matching cookies will be supplied. an example request:
Cookie: name=val; name=val2
the full spec is here:
https://www.rfc-editor.org/rfc/rfc2965
the original netscape spec is here:
http://web.archive.org/web/20070805052634/http://wp.netscape.com/newsref/std/cookie_spec.html

Resources