Sensitive Cookie with Improper SameSite Attribute
Description
The SameSite
attribute controls whether cookies are sent with cross-site requests. It helps prevent Cross-Site Request Forgery (CSRF) attacks by restricting when cookies are automatically included by the browser.
it tells the browser:
“Hey browser, only send this cookie if the request is from my own site — don’t send it for cross-site requests.”
Possible values for SameSite
are:
Strict
— The safest option.The cookie is only sent for requests from the same site. It is never sent with requests that come from another site. This blocks most CSRF attacks because malicious sites can’t trigger authenticated requests.
Lax
— A balanced option.The cookie is sent for requests from the same site and for some cross-site requests that are considered safe, like a user clicking a link or typing a URL (top-level navigation using
GET
). It is not sent for background requests like hidden forms or AJAX, which are commonly used in CSRF.None
— The least restrictive option.The cookie is always sent, even for cross-site requests. This is sometimes needed for cross-domain use cases (like third-party services or iframes), but it also opens the door for CSRF if there’s no extra protection. When using
SameSite=None
, you must also setSecure
(HTTPS only) — modern browsers enforce this.
If the SameSite
attribute is not set or is set to None
without other CSRF protections (like anti-CSRF tokens), an attacker can exploit this by crafting cross-site POST requests. The browser automatically includes the cookie, allowing unauthorized actions on behalf of the victim.
Demonstration
Example 1: Insecure Cookie Setup
javascriptCopyEditlet sessionId = generateSessionId();
let cookieOptions = { domain: 'example.com' };
// ⚠️ Missing SameSite attribute
response.cookie('sessionid', sessionId, cookieOptions);
Problem:
This cookie will be sent with any request to example.com
, including cross-site POSTs.
🧪 CSRF Attack Example
Attacker's malicious page:
htmlCopyEdit<html>
<form id="evil" action="http://local:3002/setEmail" method="POST">
<input type="hidden" name="newEmail" value="attacker@example.com" />
</form>
<script>
evil.submit();
</script>
</html>
What happens:
Victim visits this malicious page while logged in.
The form auto-submits a POST request to
http://local:3002/setEmail
.Browser sends the
sessionid
cookie automatically.The server believes it’s an authorized request from the real user — the victim’s email gets changed.
✅ Mitigation
Always set an appropriate SameSite
value for sensitive cookies — ideally Strict
or at least Lax
— and use CSRF tokens for critical actions.
Secure version:
javascriptCopyEditlet sessionId = generateSessionId();
let cookieOptions = {
domain: 'example.com',
sameSite: 'Strict' // ✅ Prevents cross-site requests from sending this cookie
};
response.cookie('sessionid', sessionId, cookieOptions);
References
OWASP: Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet
Last updated