Zum Hauptinhalt springen

Cookie-Flags richtig setzen

Secure, HttpOnly und SameSite — drei kleine Schalter, die zusammen die häufigsten Cookie-basierten Angriffe ausschließen.

Warum Cookies absichern?

Cookies — vor allem Session-Cookies — sind der Authentifizierungsmechanismus des Webs. Wer das Cookie stiehlt, ist eingeloggt. Drei klassische Angriffe zielen auf Cookies: XSS (Skript stiehlt Cookie via document.cookie), Man-in-the-Middle (Cookie wird auf dem Weg unverschlüsselt mitgelesen) und CSRF (fremde Seite nutzt das Cookie für unerlaubte Aktionen). Für jeden Angriff gibt es einen passenden Cookie-Flag — und alle drei sollten gesetzt sein.

Secure

Mit Secure sendet der Browser das Cookie nur über HTTPS. Auf einer HTTP-Verbindung wird das Cookie weder gesetzt noch zurückgeschickt. Damit kann ein Angreifer im selben WLAN keine Cookies aus einer ungesicherten Verbindung abgreifen. Pflicht für jedes Auth-Cookie.

HttpOnly

Mit HttpOnly wird das Cookie für JavaScript unsichtbar — der Zugriff über document.cookie liefert es nicht. Damit ist eine XSS-Lücke deutlich weniger gefährlich: Selbst wenn fremder Code im Browser des Nutzers läuft, kann er das Session-Cookie nicht klauen. Pflicht für jedes Auth-Cookie.

SameSite

SameSite steuert, ob das Cookie bei Cross-Site-Requests mitgeschickt wird. Drei Werte:

  • SameSite=Strict — Cookie wird nie an Cross-Site-Requests angehängt. Maximale Sicherheit, aber UX-Probleme: wer von Google auf deine Webseite klickt, ist beim ersten Aufruf nicht eingeloggt.
  • SameSite=Lax (Default seit 2020) — Cookie wird bei Top-Level-Navigation mitgeschickt (Klick auf Link), aber nicht bei iframes, Bildern oder POST-Requests von fremden Seiten. Guter Kompromiss.
  • SameSite=None — Cookie wird immer mitgeschickt. Erfordert zusätzlich Secure. Nur nötig für Drittanbieter-Cookies (Tracking, eingebettete Widgets).

__Host- und __Secure-Präfixe

Spezielle Cookie-Namen-Präfixe erzwingen bestimmte Flags. Cookies, die mit __Host- beginnen, müssen Secure, kein Domain-Attribut und Path=/ haben. __Secure- erzwingt nur Secure. Beide Präfixe schützen zusätzlich gegen Cookie-Tossing-Angriffe von Subdomains.

Konfigurationsbeispiele

Flask:

app.config['SESSION_COOKIE_SECURE']    = True
app.config['SESSION_COOKIE_HTTPONLY']  = True
app.config['SESSION_COOKIE_SAMESITE']  = 'Lax'

Express (Node.js):

app.use(session({
  cookie: { secure: true, httpOnly: true, sameSite: 'lax' }
}))

PHP (session.cookie_secure etc. via php.ini oder ini_set):

session.cookie_secure   = 1
session.cookie_httponly = 1
session.cookie_samesite = "Lax"

Was Cookie-Flags nicht schützen

  • Logische CSRF trotz SameSite=Lax — bei GET-Requests, die State ändern (sollten sie eh nicht). Lösung: GET = read-only, sonst CSRF-Token.
  • Session-Hijacking via XSS — wenn der Angreifer Code direkt in deinem Kontext ausführen kann, kann er Aktionen statt Cookies nutzen. CSP gegen XSS bleibt wichtig.
  • Cookie-Inhalt — Flags schützen den Transport, nicht den Inhalt. Sensible Daten gehören nicht ins Cookie, sondern serverseitig in den Session-Store.

Empfehlung

Für jedes Auth-Cookie: Secure; HttpOnly; SameSite=Lax. Bei strikter Sicherheit (Banking, Admin-Panels): SameSite=Strict. Ein zusätzlicher __Host--Präfix kostet nichts und schließt Sub-Domain-Angriffe aus.

Selbst prüfen: HTTP-Header

HSTS, CSP, X-Frame-Options & Co. Gib eine Domain ein und sieh in Sekunden, wie es um deinen COOKIE-FLAGS steht.

Auch im Lexikon