Cookie stored in the browser (Chrome) contains 8 fields:
- Name: The cookie’s name.
- Value: The cookie’s value.
- Domain: The cookie’s domain.
- Path: The cookie’s path.
- Expires / Maximum Age: The cookie’s expiration time, or maximum age. For session cookies, this field is always “Session”.
- Size: The cookie’s size in bytes.
- Secure: If present, indicates that communication for this cookie must be over an encrypted transmission.
When reveiving an HTTP request, a server can send a
Set-Cookie header with the
response. The cookie is usually stored by the browser, and then the cookie is
sent with requests made to the same server inside a
Cookie HTTP header. An
expiration date or duration can be specified, after which the cookie is no
longer sent. Additionally, restrictions to a specific domain and path can be
set, limiting where the cookie is sent.
Set-Cookie HTTP response header sends cookies from the server to the user
agent. A simple cookie is set like this:
The header from the server tells the client to store a cookie.
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: k1=v1 Set-Cookie: k2=v2
Now, with every new request to the server, the browser will send back all
previouly stored cookies to the server using
GET /my_page.html HTTP/1.1 Host: www.example.org Cookie: k1=v1; k2=v2
The cookie created above is a session cookie: it didn’t specify an
Max-Age directive. However, web browsers may use session restoring, which
makes most session cookies permanent, as if the browser was never closed.
Permanent cookies is different from session cookies. They expire at a specific
Expires or after a specific length of time
Max-Age. Note that when an
expiry date is set, the time and date set is relative to the client where the
cookie is being set on, not the server.
Set-Cookie: id=123; Expires=Fri, 20 Oct 2017 09:00:00 GMT;
According to [IETF RFC 2109][rfc2109], Hosts names can be specified either as an IP address or a FQHN string. Sometimes we compare one host name with another. Host A’s name domain-matches host B’s if
- both host names are IP addresses and their host name strings match exactly; or
- both host names are FQDN strings and their host name strings match exactly; or
- A is a FQDN string and has the form NB, where N is a non-empty name
string, B has the form .B’, and B’ is a FQDN string. (So,
Note that domain-match is not a commutative operation:
.c.com, but not the reverse.
A secure cookie is only sent to the server with a encrypted request over the
HTTPs protocol. Even with
Secure, sensitive information should never be stored
in cookies, as they are inherently insecure and this flag cannot offer real
To prevent cross-site scripting (XSS) attacks,
HttpOnly cookies are
Document.cookie API; they are only sent to the
server. For example, cookies that persist server-side sessions don’t need to be
HttpOnly flag should be set.
Set-Cookie: id=123; Expires=Fri, 20 Oct 2017 09:00:00 GMT; Secure; HttpOnly
Print Cookies from JS
Open the console of Chrome, then past the following command:
Or pretty print using
After reading a lot of stuff from the internet, now let’s create a cookie ourselves. Here, I’m using 3 software:
- Server: Jekyll, a static blog generator running on
- Proxy: ZAP proxy listening and intercepting the traffic on
- Client: Firefox, in non-private mode, receiving traffic from
I set a breakpoint to the proxy, so that I can add a
Set-Cookie header to the
HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Set-Cookie: proxy=ZAP; Expires=Fri, 20 Oct 2017 09:00:00 GMT; HttpOnly
All the information can be seen from the browser cookie inspector:
proxy: "ZAP" CreationTime: "Thu, 19 Oct 2017 20:17:58 GMT" Domain: "localhost" Expires: "Fri, 20 Oct 2017 09:00:00 GMT" HostOnly: true HttpOnly: true LastAccessed: "Thu, 19 Oct 2017 20:17:58 GMT" Path: "/" Secure: false
However, it doesn’t not shown from the console using