Using the Same-Site Cookie Attribute to Prevent CSRF Attacks

This article looks into the details of how the Same-Site cookie attribute works and how it can be used to help prevent malicious cross-site request forgery (CSRF) attacks.

Introduction to Web Cookies

Because HTTP is a stateless protocol, it cannot internally distinguish one user from another. To address this issue, cookie technology was invented in 1994. By using cookies, servers instruct browsers to save a unique key and then send it back with each request made to the server.

When a request is sent from a browser to a website, the browser checks if it has a stored cookie that belongs to that website. While carrying out this process, it checks to see whether the properties and flags of the cookies (domain, path, secure), match the website’s data which has been requested. If they match, the browser sends the relevant cookies along with the request.

Cookies Misuse Can Lead to Cross-site Request Forgery

This behavior is also repeated in the same way for requests made by third parties through the browser. By “third parties” we mean other websites that we don’t visit directly. The critical point from a web application security perspective is that when you visit website A, all cookies kept in the browser for site B will be added to the request initiated toward site B by site A. So, a session that belongs to B on the browser can be used and even abused in this way.

This block diagram explains how cross-site cookie requests workIn security terminology, abusing this behavior of browsers is known as Cross-site Request Forgery (CSRF).  It is carried out by misusing a session belonging to an authorized user by using this browser behavior.

This browser behavior can also be misused for other purposes like tracking users or advertising. When you enter a site, for instance example.com, your browser may make a few requests to different sites because of the HTML elements placed on the page of example.com, for example Facebook Like buttons, Google Analytics code, etc. Along with these requests, the cookies in the browser that belong to these other sites will also be sent. Therefore those third parties can track and log your activity by using Cookie and Referrer information.

Should You Block Cross-site Requests to Prevent CSRF?

Normally, it is possible to avoid tracking like this in Firefox and Chrome browsers.  However, when these browsers block tracking, they prevent the sending of cookies along with the request made by any third party website. But by doing so your browsing experience will be very poor. So by blocking cookies, you can totally prevent CSRF, but is it worth the consequences?

Introducing the Same-Site Cookie Attribute to Prevent CSRF Attacks

Thanks to a new cookie security flag, that Google Chrome started supporting on the 29th of March, and other the popular browsers followed, there is now a solution. It is called the Same-Site cookie attribute. Developers can now instruct browsers to control whether cookies are sent along with the request initiated by third party websites – by using the SameSite cookie attribute, which is a more practical solution than denying the sending of cookies.

Setting a Same-Site attribute to a cookie is quite simple. It consists of adding just one instruction to the cookie.  Simply adding ‘SameSite=Lax’ or ‘SameSite=Strict’ is enough!

Set-Cookie: CookieName=CookieValue; SameSite=Lax;
Set-Cookie: CookieName=CookieValue; SameSite=Strict;

Differences Between the Strict and Lax SameSite Cookie Attributes

Strict: As the name suggests, this is the option in which the Same-Site rule is applied strictly.  When the SameSite attribute is set as Strict, the cookie will not be sent along with requests initiated by third party websites.

Setting a cookie as Strict can affect browsing experience negatively. For example, if you click on a link that points to a Facebook profile page, and if Facebook.com has set its cookie as SameSite=Strict, you cannot continue navigation on Facebook (view the Facebook page) unless you log in to Facebook again. The reason for this is because Facebook`s cookie was not sent by this request.

Lax: When you set a cookie’ SameSite attribute to Lax, the cookie will be sent along with the GET request initiated by third party website.

The important point here is that, to send a cookie with a GET request, GET request being made must cause a top level navigation. Only in this way, the cookie set as LAX will be sent. Let me explain more.

Resources can be loaded by iframe, img tags, and script tags. These requests can also operate as GET requests, but none of them cause TOP LEVEL navigation. Basically, they don’t change the URL in your address bar. Because these GET requests do not cause a TOP LEVEL navigation, thus cookies set to Lax won’t be sent with them.

See the table below for more clarification:

Request TypeExample CodeCookies sent
Link<a href=”…”></a>Normal, Lax
Perender<link rel=”prerender” href=”..”/>Normal, Lax
Form GET<form method=”GET” action=”…”>Normal, Lax
Form POST<form method=”POST” action=”…”>Normal
iframe<iframe src=”…”></iframe>Normal
AJAX$.get(“…”)Normal
Image<img src=”…”>Normal

Does this really mean “goodbye” to CSRF?

Yes, it looks like the SameSite cookie attribute is an effective security measure against CSRF attacks. You can avoid sending your cookies with the request initiated by third parties by using this feature.  Let me clarify with an example:

Let’s say you are logged in to the website www.badbank.com.  Using a phishing attack, an attacker can trick you into entering www.attacker.com in another browser tab. Using a code on www.attacker.com, the attacker tries to transfer money from your account by posting a FORM to www.badbank.com. Your browser sends the cookie belonging to www.badbank.com with this request. If the form on www.badbank.com lacks CSRF tokens to prevent a CSRF attack, your session can be exploited by the attacker.

If the cookie of www.badbank.com had been set to SameSite=Lax, the cookie in the browser would not have been sent with the POST request and the attack would not be successful.

CSRF Popularity is Going Down

CSRF attacks were at number 5 in the OWASP Top 10 list published in 2010, but they declined to number 8 in the OWASP Top Ten in 2013. People suggested that the reason for this was increased awareness of CSRF and the common use of Anti-CSRF tokens by frameworks.

Source : https://www.owasp.org/index.php/Top_10_2013-Release_Notes

Preventing CSRF Vulnerabilities

Although we’re now using the SameSite Cookie attribute, we should still be cautious! We should make the whole changes with POST request instead of GET.

GET is designed for navigational purposes, not for state changes, so using GET requests is generally considered a safe method.  However, when we are performing actions (such as ordering a product, changing a password, or editing profile information), using POST requests is much safer.

There are 3 important reasons for this:

  • When the parameters are carried by GET, they stay in the browser history. They also will be placed in server logs and the Referrer header in the request made toward third parties.
  • Another reason for not using GET requests is that cookies set to Lax are still sent along with GET requests, giving attackers another opportunity to exploit users.
  • Lastly, exploiting a CSRF vulnerability by using GET is much easier. To exploit a CSRF vulnerability in a form using GET, an attacker does not have to own a site. He can inject this payload into a forum message, post comment or image tag.

How Does Netsparker report this?

At Netsparker, we are constantly paying attention to the latest security developments and adding new features and security checks into our engine. In fact just a few weeks after the technical details of the Same-Site cookie attribute were released, we implemented the check for it in both Netsparker Desktop and Netsparker Enterprise, therefore the web vulnerability scanner will alert you if cookies do not have such attribute.

Netsparker identified a cookie that does not use the Same-Site attribute