HTTP Cookies

An HTTP Cookie (also known as a Web Cookie or browser Cookie) is a small piece of data that a server sends to a user’s browser and keeps locally. It is carried and sent to the server the next time the browser makes a request to the same server. Cookies make it possible to record stable state information over stateless HTTP protocols.

Cookies feature

  • Front-end data storage
  • The backend is set through HTTP headers
  • Requests are sent via HTTP headers to the back end
  • Front-end read-write
  • Comply with the Same Origin Policy (Protocol, domain name, port)
  • The period of validity
  • Path (at what level of the site, the level of the site URL)
  • http-only
  • secure

Create a Cookie

When the server receives an HTTP request, the server sets the Cookie by adding the set-cookie option to the response header. The browser usually saves the Cookie automatically after receiving the response, and sends the Cookie information to the server through the Cookie request header in each subsequent request to the server.

Set_cookie response header configuration

Set-cookie: < Cookie name >=< Cookie value >

The server sends Cookle information to the user agent (browser) using the set-cookie response header

The browser adds the Cookie request header

GET /sample_page.html HTTP/1.1

Host: www.example.org

Cookie: yummy_cookie=choco; tasty_cookie=strawberry

For each request to the server, the browser will automatically send the previously saved Cookie information to the target server through the Cookie request

Define the Cookie lifecycle

Phase session cookies

The browser will be automatically deleted when closed. The deletion takes effect only during the session.

A persistent Cookie

The lifetime of a persistent Cookie depends on an expiration or max-age period of time

The validity time of setting the cookie value is 20:53 on May 6, 2021

Set-Cookie: id=a3fWa; Expires=Thu, 06 May 2021 12:53:27 GMT;  
Copy the code

The Expires value is set to the GMT time format, which is 8 hours less than the current time. Take the current time as an example, the conversion is as follows:

let time = new Date()
time.toGMTString()
//"Thu, 06 May 2021 12:53:27 GMT"
Copy the code

Tip: When Cookie expiration is set, the date and time are only relevant to the client, not the server.

Cookie expires

If the Cookie does not set expires, the lifetime of the Cookie is only for the current session. Closing the browser means the session ends and the Cookie expires.

Set-Cookie: id=a3fWa; Expires=Thu, 05 May 2021 12:53:27 GMT;
Copy the code

Expires Sets a past time, so the cookie will be deleted immediately.

Restricting access to cookies

Secure properties

Cookies marked Secure should only be sent to the server through requests that are encrypted by the HTTPS protocol

HttpOnly attribute

JavaScript Document.cookie API cannot access cookies with HttpOnly attributes; This type of Cookie applies only to the server. Example:

Set-Cookie: id=abed; Expires=Thu, 06 May 2021 12:53:27 GMT; Secure; HttpOnly
Copy the code

Cookie scope

The Domain and Path identifiers define what the Cookie does: that is, allow the URL to which the Cookie should be sent.

Domain properties

Domain specifies which Domain names (hosts) can hold cookies. If this parameter is not specified, the default value is Origin and the subdomain name is not included. If Domain is specified, subdomain names are generally included.

For example, if you set Domain=example.com, cookies are also included in the subdomain (such as developer.example.com).

Path properties

The Path identifier specifies which paths under the domain name (host) can hold cookies (the URL Path must exist in the request URL). Child paths are also matched with the character %x2F (“/”) as the path separator. For example, if you set Path=/list, the following paths will match:

  • /list
  • /list/detail
  • /list/detail/main

SameSite properties

SameSite cookies allow the server to request that a Cookie not be sent during cross-site requestsCopy the code

Example:

Set-Cookie: key=value; SameSite=Strict

SameSite has the following three values:

  • None

Browsers continue to send cookies under same-site and cross-site requests, case insensitive.

  • Strict

The browser will only send cookies when visiting the same site.

  • Lax

Similar to Strict, except when the user navigates to a URL from an external site (for example, via a link). In newer browsers, same-site cookies will be reserved as the default for cross-site sub-requests, such as image loads or calls to frames, but will only be sent when the user navigates to a URL from an external site.

Cookies role

  • Store personalization (such as user-defined Settings, themes, and so on)
  • Store the unique identifier of a user when the user is not logged in
  • Store credentials of users who have logged in
  • Store other service data

. This parameter can be selected flexibly based on service scenarios

Cookie- Login user credentials

  • The user ID

Example:

userId=1; Uid userId _ga = GA1.1.245187848.1620008273 / / userId - > = 142389; _ga = GA1.1.245187848.1620008273 / / userId - > work number...Copy the code

The above login user cookie information, attackers can easily calculate the cookies of other users, so as to impersonate other user identity.

  • User ID+ signature

Attackers can easily guess the rule of userId preservation through the cookies saved above, and change the logged cookie information by some means, so that they can impersonate the identity of other users. In this case, we would want to sign the userId, but the userId backend interface can not reverse sign, and the signature can still be changed, and how should the interface identify ni? The right thing to do is:

Both the signature and the real userId are transparently transmitted to the interface. After receiving the signature and userId, the interface uses the same signature algorithm as the front-end to calculate the signature result and compare it with the original signature to confirm the accuracy of the user information.Copy the code
// crypt.js
var crypt ={};
const key ='fs)3! dsg/8%';// Key is defined arbitrarily, the more arbitrary the security
crypt.cryptUerId = function(userId){
    var crypto = require('crypto');
    var sign = crypto.createHash('sha256',key);
    sign.update(userId+' ');
    return sign.digest('hex')}module.exports = crypt;
Copy the code
// login.js
const crypt =require('.. /tools/crypt')
let sign = crypt.cryptUerId(user.id)
// userId and sign need to be passed through here, because the interface cannot reverse sign sign into the original userId, it can only use the same signature algorithm to sign the userId again, and verify the signature value twice
ctx.cookies.set('userId', user.id,{ httpOnly: false.sameSsecure: false });
ctx.cookies.set('sign', sign,{ httpOnly: false.sameSsecure: false });
Copy the code
// addComment.js
const crypt = require('.. /tools/crypt')...let userId = ctx.cookies.get('userId');
let sign=ctx.cookies.get('sign')
if(sign! ==crypt.cryptUerId(userId)){throw new Error('Somebody's messing around! ')}Copy the code
  • SessionId (JWT)

After the user accesses the target host, the host interface generates the sessionId according to a certain encryption algorithm and saves it in the cookie. The sessionId will be carried in each subsequent request as the user identity identification mark.

//session.js
var session = {};
var cache = {};
session.set = async function (sessionId, obj) {
    var sessionId = Math.random();// Generate the sessionId randomly
    if(! cache[sessionId]){ cache[sessionId]={} } cache[sessionId].content =obj;return sessionId;
}
session.get = function (sessionId) {
    return cache[sessionId]&& cache[sessionId].content
}
module.exports = session;
Copy the code
// login.js
const session = require('.. /tools/session')...var sessionId = session.set(user.id,{userId:user.id});
ctx.cookies.set('sessionId',sessionId,{ httpOnly: false.sameSite: "Lax".secure: false })
Copy the code
// addComment.js.var sessionId = ctx.cookies.get('sessionId');
var sessionObj = session.get(sessionId);
if(! sessionObj || ! sessionObj.userId){throw new Error('Session does not exist')}...Copy the code

Relationship between Cookies and XSS

  • XSS may steal Cookies (Document.cookies)
  • Set http-only cookies to not be stolen (cookies can only be transmitted through HTTP requests)

The relationship between cookies and CSRF

  • CSRF takes advantage of user Cookies
  • The attack site cannot read or write Cookies
  • It is best to prohibit third parties from using Cookies (using same-site)

Cookies- Security policies

  • Signature tamper-proof (verify that cookies are modified)
  • Private changes (save after encryption)
  • HTTP – only (to prevent XSS)
  • Secure (prevents cookie theft only over HTTPS)
  • Same-site (Disabling Cookies used by third parties)

References:

MDN_HTTP cookies node_crypto- Five minutes of encryption will take you to understand what JWT is

conclusion

Cookies, as the focus of security defense, are worth further study. Cookies do more than that, of course. This paper records the author in the development process encountered problems caused by the thinking and exploration. For the reference of readers with similar problems. Other security aspects of the article I will continue to update, welcome readers to put forward comments and suggestions.