Skip to main content

Insecurely generated cookies - SameSite

Need

Secure generation of cookies with proper SameSite attribute setting

Context

  • Usage of PHP 7.0 for server-side scripting and web development
  • Usage of Closure for JavaScript code optimization and minification
  • Usage of Illuminate\Http\Request for handling HTTP requests in Laravel
  • Usage of Cookie for handling HTTP cookies in a Node.js application

Description

Non compliant code

<?php

namespace App\\Http\\Middleware;

use Closure;
use Illuminate\\Http\\Request;

class AddCookieToResponse
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);

$response->headers->setCookie(
new Cookie(
'cookie_name',
'cookie_value',
time() + (86400 * 30), // Cookie will expire after 30 days
'/',
null,
false,
true
)
);

return $response;
}
}

The above code is a middleware in Laravel which adds a cookie to the response. The cookie is set with the name 'cookie_name' and the value 'cookie_value'. The cookie will expire after 30 days.

However, the issue with this code is that it doesn't set the SameSite attribute for the cookie. The SameSite attribute is a security measure that helps prevent cross-site request forgery (CSRF) attacks. It does this by restricting how cookies are sent with cross-site requests.

In the above code, the SameSite attribute should be set when creating the cookie. Without it, the application's cookies are generated insecurely, which could potentially expose the application to CSRF attacks.

Steps

  • Identify the part of the code where the cookie is being set.
  • Add the SameSite attribute to the cookie settings. This attribute helps to prevent cross-site request forgery (CSRF) attacks.
  • Set the SameSite attribute to 'Strict' or 'Lax' depending on the requirements of your application. 'Strict' will prevent the cookie from being sent in all cross-site browsing context, while 'Lax' allows it for some.
  • Ensure that the SameSite attribute is set every time a cookie is created or updated.

Compliant code

<?php

namespace App\\Http\\Middleware;

use Closure;
use Illuminate\\Http\\Request;
use Symfony\\Component\\HttpFoundation\\Cookie;

class AddCookieToResponse
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);

$response->headers->setCookie(
Cookie::create(
'cookie_name',
'cookie_value',
time() + (86400 * 30), // Cookie will expire after 30 days
'/',
null,
false,
true,
false,
'strict' // SameSite attribute set to 'strict'
)
);

return $response;
}
}

The updated code now includes the SameSite attribute in the cookie settings. This attribute is set to 'strict', which means the cookie will not be sent along with requests initiated by third party websites. This is a security measure that helps to prevent cross-site request forgery (CSRF) attacks.

The SameSite attribute is added as an argument in the Cookie::create method. The false argument before 'strict' is for httpOnly. When httpOnly is set to true, the cookie cannot be accessed through client side script. This also helps to mitigate against cross-site scripting (XSS) attacks.

The 'strict' value for the SameSite attribute means the browser will only send cookies if the request originated from the website that set the cookie. If the request originated from a third party website, the cookie will not be included in the request. This is the most secure setting, but it can cause functionality issues with some types of cross-domain requests.

If your application requires some level of cross-domain requests, you can set the SameSite attribute to 'lax'. This will still provide a level of protection against CSRF attacks, but it allows cookies to be included in top-level navigations.

References