Skip to main content

Insecurely generated cookies - SameSite

Need

Enforce secure generation of cookies with proper SameSite attribute configuration

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing and organizing data in a Node.js application

Description

Non compliant code

import 'package:shelf/shelf.dart' as shelf;

shelf.Response handleRequest(shelf.Request request) {
var response = shelf.Response.ok('Hello, World!');
return response.change(headers: {
'Set-Cookie': 'sessionId=123456; Secure; HttpOnly'
});
}

The above Dart code is used to handle HTTP requests in a backend application using the Shelf framework. The handleRequest function creates a response with the text 'Hello, World!' and sets a cookie named sessionId with a value of 123456.

The cookie is marked as Secure and HttpOnly, which are good practices as they respectively ensure the cookie is only sent over HTTPS and prevent the cookie from being accessed through client-side scripts.

However, the code has a significant vulnerability: it does not set the SameSite attribute for the cookie.

The SameSite attribute is a security measure that browsers can use to decide whether to send cookies along with cross-site requests. If SameSite is not set, the browser will default to sending cookies on all requests, including cross-site ones. This can expose the application to Cross-Site Request Forgery (CSRF) attacks, where an attacker tricks a victim into performing actions on a web application in which they're authenticated.

To fix this vulnerability, the SameSite attribute should be set to Strict or Lax depending on the needs of the application. Strict will prevent the cookie from being sent on all cross-site requests, while Lax allows cookies to be sent when the user navigates to the URL from an external site.

Steps

  • Identify all places in the code where cookies are being set.
  • Add the 'SameSite' attribute to the 'Set-Cookie' header.
  • Set the 'SameSite' attribute to 'Strict' or 'Lax' depending on your needs. 'Strict' will prevent the cookie from being sent by the browser to the target site in all cross-site browsing context, even when following a regular link. 'Lax' allows the cookie to be sent when the user navigates to the cookie's origin site.
  • Test the application to ensure that the changes do not break any functionality and that the cookies are being set correctly with the 'SameSite' attribute.

Compliant code

import 'package:shelf/shelf.dart' as shelf;

shelf.Response handleRequest(shelf.Request request) {
var response = shelf.Response.ok('Hello, World!');
return response.change(headers: {
'Set-Cookie': 'sessionId=123456; Secure; HttpOnly; SameSite=Strict'
});
}

The original code was setting a cookie without the SameSite attribute. This attribute is crucial for preventing cross-site request forgery (CSRF) attacks. It asserts that a cookie must not be sent with cross-origin requests, providing some protection against cross-site request forgery attacks.

In the fixed code, we have added the SameSite attribute to the Set-Cookie header and set it to Strict. This means the cookie will only be sent in a first-party context, i.e., it is sent only if the URL of the request matches the cookie's domain. This is the most secure setting, but it might not be suitable for all applications. If your application needs to send cookies with cross-origin requests, you can set SameSite to Lax.

Remember to test your application thoroughly after making these changes to ensure that no functionality is broken and that the cookies are being set correctly with the SameSite attribute.

References