Know The Web: HTTP Cookie 🍪

souvikinator

Souvik Kar Mahapatra

Posted on February 17, 2021

Know The Web: HTTP Cookie 🍪

In this post, we are going to learn about Cookie certainly not the edible one. We'll discuss cookie properties and security stuff related to HTTP cookies, also create cookie on the way so make sure that you and your patience grab milk and cookie, enjoy the post.

Cookie Time!

While using Facebook, Instagram, or any other services online did you notice that once you logged into these services you don't have to log in when you visit these sites again?
You searched for shoes and the next moment when you visit any site, you get to see ads related to shoes.

Is there some mind-reading stuff going on?

sorcery

To define, cookies are small chunks of temporary data (key-value pair) in the browser which helps in various functionalities in any web services (as mentioned above). These web services/websites setup cookie into your browser and use for features like managing you session on their service/website, to track you and stuff like that. They can also be used to remember pieces of information that the user previously entered into form fields, such as names, addresses, passwords(not a good idea😅), and payment card numbers.

Now as these websites/web services are able to access the cookie they place in your browser which makes it clear that, "every time you make a request to the website/web service, the cookie is sent to the server along with the request".

🕵️‍♂️ Sherlock mode ON!

Let's head over to a random site and have a look at their cookies. On the way, I'll explain about the properties. So I am heading to motherfuckingwebsite.com. In developer tools open the Application tab and then to cookie > https://mothe....
There you get to see the following:

cookies-application.png

Those with green underline are options. Name & Value are self explanatory. The rest are what we need to understand.

  • Domain

Each cookie has a domain pattern to which it belongs and can only be accessed by that specific domain pattern.

If a cookie named cookie-1 is added for .motherfuckingwebsite.com (notice the .) then cookie-1 can be accessed by any subdomain of motherfuckingwebsite.com. Example: cookie-1 can be accessed by the domain motherfuckingwebsite.com as well as its subdomain like www.motherfuckingwebsite.com or www2.motherfuckingwebsite.com and so on.

If a cookie named cookie-2 is added for a subdomain xyz.motherfuckingwebsite.com then it can be only accessed by its subdomain and itself. Example: cookie-2 can be accessed by subdomain xyz.motherfuckingwebsite.com and its subdomain abc.xyz.motherfuckingwebsite.com and so on.

you can read more at RFC2109

  • Path

Suppose you want to make a cookie accessible to a specific path then this option is used. Will explain in a while.

  • Expires/Max-age

As I have mentioned right in the start that "cookies are temporary data" i.e they have a validity duration after which they expire. How is validity duration determined? By the web service/website. Whenever a website/web service creates a cookie, it also mentions its lifetime.

HttpOnly, Secure and SameSite will be explained in the security section.

Okay! enough talks. Let's create some cookies, heat up your oven (browser)

👨‍💻 The Client Way

First we'll discuss about creating cookie from the client-side i.e from the browser using JS which is pretty easy.

document.cookie

How about having a look at existing cookie using JS? Just use document.cookie in the console and you'll see the following:

cookies-console.png

Notice, each cookie is separated by a semicolon(;).

  • creating simple cookie
document.cookie="itsME=1"
Enter fullscreen mode Exit fullscreen mode

NOTE: Above code doesn't override cookies. It only created a new one.

cookie-bake.png

You can see it's defined for domain motherfuckingwebsite.com now as per the properties we have discussed above, www.motherfuckingwebsite.com should not be able to access the cookie itsME.

cookie-subdomain.png

and we don't see the cookie that we created hence we verified the properties.

  • setting up cookie path

How about adding the Path option to our cookie? Let's go...

document.cookie="itsMe=7; path=/test";
Enter fullscreen mode Exit fullscreen mode

The above code will only set cookie for motherfuckingwebsite.com/test and can only be accessed by it. Here is the example.

document.cookie="itsME=7; path=/test";
Enter fullscreen mode Exit fullscreen mode

cookie-path.png

Image 1: we are accessing cookie from motherfuckingwebsite.com and there is no such cookie.

Image 2: we are accessing cookie from motherfuckingwebsite.com/test and we can see it.

  • Setting cookie lifetime

Let's create a cookie with an expiry date. Now we can do this in two ways.

  1. Expires: Takes date as value.
//86400e3 is same as 86400000 i.e 24 hours in milliseconds
var exp_date=new Date(Date.now()+86400e3);
//refer template literals in JS if not familiar with ${}
document.cookie=`itsME2=2;expires=${exp_date.toGMTString()}`; 
Enter fullscreen mode Exit fullscreen mode
  1. Max-age: Takes time (in seconds) as value.
//86400 i.e 24 hours in seconds
document.cookie=`itsME3=3;max-age=86400`; 
Enter fullscreen mode Exit fullscreen mode

Above we have created both the cookie with a validity of 24 hrs. from the time the cookie was created. Here you can compare all three cookies we have set so far.

cookie-expire.png

Notice! in the Expires/Max-age part you can see ItsME2 and ItsME3 has some date and time but ItsME shows session. It is so because when you don't mention any expiry time of the cookie then the browser considers it as a sessional cookie and it expires as soon as you close the browser. Go ahead, give it a try.

💡 Head over to didthanoskill.me and look for cookie from the URL bar. You'll see 1 cookie in use. When you do document.cookie in the browser console, an empty string is returned which is weird. Go to the Application tab in the developer tool and there also you'll see no cookie. Any idea why is so? Hint: have a look at the source and if still don't understand then run the debugger in the dev tool to understand why is it happening so?

🖥️ The Server Way

We saw the client's Way of creating cookies. Now we'll create a cookie from the server-side and I'll use NodeJS and express for this.

Basically what happens is when the client makes a request to the server, the server responds with a response which contains header and in that header, there is set-cookie option which tells the browser to create a cookie.

  • creating a simple cookie.
const app=require("express")();
app.get("/",(req,res)=>{
    //setting response header
    res.setHeader("set-cookie",["itsSERVER1=h1"]); 
    res.send("this is https://localhost:2000/");
});

app.listen(2000,()=>{
    console.log(">2000<");
})
Enter fullscreen mode Exit fullscreen mode

and we have it.

  • setting up cookie path
const app=require("express")();
app.get("/",(req,res)=>{
    /*can also use res.setHeader() instead of
    res.cookie()*/
    res.cookie("itsSERVER1","h1");
    //for path /hahahayes
    res.cookie("itsSERVER2","yeet!",{path:"/hahahayes"});  
    res.send("this is https://localhost:2000/");
});

app.get("/hahahayes",(req,res)=>{
    res.send("this is https://localhost:2000/hahahayes");
});

app.listen(2000,()=>{
    console.log(">2000<");
});
Enter fullscreen mode Exit fullscreen mode

gives following result:

cookie-ss-path.png

cookie-ss-path2.png

so on and so forth for other options as well.

🔒 Security

Security is a very important topic of discussion over here. As mentioned earlier, services like social media use various cookies to keep you logged in. If such cookies get in hands of attackers they can easily break into your account and the rest you know.

When user privacy is a concern, it's important that any web app implementation invalidate cookie data after a certain timeout instead of relying on the browser to do it.

If you are using cookie to store some data and later rendering it in DOM (which is a super duper bad practice) then make sure to keep the valid formatting, they should be escaped using a built-in encodeURIComponent function:

var cookie_name="mycookie";
var cookie_value="myvalue";
document.cookie = `${encodeURIComponent(cookie_name)}=${encodeURIComponent(cookie_value)}`;
Enter fullscreen mode Exit fullscreen mode

In section The Client Way, we easily accessed the website's cookie using JavaScript, so an attacker may find a vulnerability like XSS which enables them to execute malicious JS code on the website and bypass logins. From a developer's point of view, it's really hard to keep track of XSS especially in humongous applications with a lot of features. Due to this, some inbuilt security features are there in cookies, which prevent such attacks even if the attacker is able to execute some code.

You can check out Hack this site basic 10 which demonstrates, what careless use of cookies can lead to.

HttpOnly is an option used by web-server when they set cookies. This option forbids any JavaScript access to the cookie. This is a precautionary measure, to protect from certain attacks.

//server side
const app=require("express")();
app.get("/",(req,res)=>{
    /*can also use res.setHeader() instead of
    res.cookie()*/
    res.cookie("itsSERVERsecure","100",{httpOnly:true});  
    res.send("this is https://localhost:2000/");
});

app.listen(2000,()=>{
    console.log(">2000<");
});
Enter fullscreen mode Exit fullscreen mode

and you'll see a tick mark (✔️) under HttpOnly in the Application tab (developer tools). Try accessing it using JS.

If your cookie contain sensitive content then you may wanna send it over HTTPS. To accomplish this you have to include secure option as shown below.

//client side
document.cookie = "ItsMeSecure=6; secure";
Enter fullscreen mode Exit fullscreen mode
//server side
const app=require("express")();
app.get("/",(req,res)=>{
    /*can also use res.setHeader() instead of
    res.cookie()*/
    res.cookie("itsSERVERsecure","100",{secure:true});  
    res.send("this is https://localhost:2000/");
});

app.listen(2000,()=>{
    console.log(">2000<");
});
Enter fullscreen mode Exit fullscreen mode

samesite SameSite prevents the browser from sending the cookie along with cross-site requests. Possible values are lax, strict or none.

The lax value will send the cookie for all same-site requests and top-level navigation GET requests. This is sufficient for user tracking, but it will prevent many CSRF attacks. This is the default value in modern browsers.

The strict value will prevent the cookie from being sent by the browser to the target site in all cross-site browsing contexts, even when following a regular link.

The none value explicitly states no restrictions will be applied. The cookie will be sent in all requests—both cross-site and same-site.

So make sure that you use cookies wisely 🦉.
Feel free to point out any issues or suggest improvements in the content.

🥳 So it's time to wrap up the post with a quote

"Opportunities don't happen. You create them" -Chris Grosser

💖 💪 🙅 🚩
souvikinator
Souvik Kar Mahapatra

Posted on February 17, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Know The Web: HTTP Cookie 🍪
webdev Know The Web: HTTP Cookie 🍪

February 17, 2021