Sensibler Cookie in HTTPS-Session ohne 'Secure'-Attribut
Beschreibung
Sensibler Cookie in HTTPS-Session ohne 'Secure'-Attribut tritt auf, wenn ein Cookie mit sensiblen Daten (wie Session-Tokens, Authentifizierungs-Tokens oder Benutzer-Credentials) ohne das Secure-Flag gesetzt wird. Ohne dieses Flag sendet der Browser das Cookie über unverschlüsselte HTTP-Verbindungen, selbst wenn das Cookie ursprünglich über HTTPS gesetzt wurde. Angreifer, die Man-in-the-Middle-Angriffe durchführen, können diese Cookies abfangen, wenn Benutzer auf irgendeine HTTP-Ressource zugreifen, selbst auf anderen Sites.
Risiko
Fehlendes Secure-Flag auf sensiblen Cookies ermöglicht Cookie-Diebstahl durch Netzwerk-Interception. Selbst auf Sites, die HTTPS erzwingen, sendet der Browser nicht-sichere Cookies über HTTP, wenn der Benutzer irgendeine HTTP-Ressource besucht (einschließlich Bilder oder Redirects). Angreifer in geteilten Netzwerken (WLAN-Hotspots, Unternehmensnetzwerke) können diese Cookies leicht erfassen. Session-Hijacking durch Cookie-Diebstahl bleibt einer der häufigsten Web-Angriffe. Der Angriff erfordert minimale Fähigkeiten mit Tools wie Wireshark oder Firesheep.
Lösung
Setzen Sie immer das Secure-Flag auf Cookies, die sensible Daten enthalten. Verwenden Sie HTTPS für alle Anwendungsressourcen. Implementieren Sie HTTP Strict Transport Security (HSTS), um HTTP-Downgrade-Angriffe zu verhindern. Setzen Sie angemessene Cookie-Attribute: Secure, HttpOnly, SameSite. Verwenden Sie Framework-Standardeinstellungen, die Sicherheitsattribute automatisch anwenden. Überprüfen Sie Cookie-Einstellungen regelmäßig. Erwägen Sie die Verwendung von __Host- oder __Secure-Cookie-Präfixen für zusätzlichen Schutz.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Session-Diebstahl Session-Cookies, die über HTTP übertragen werden, können abgefangen werden und ermöglichen Session-Hijacking. |
| Zugriffskontrolle | Bereich: Kontoübernahme Gestohlene Authentifizierungs-Cookies ermöglichen Angreifern, Benutzer zu imitieren. |
| Integrität | Bereich: Unbefugte Aktionen Angreifer mit gestohlenen Sessions können Aktionen als Opferbenutzer durchführen. |
Beispielcode + Lösungscode
Verwundbarer Code
# VERWUNDBAR: Session-Cookie ohne Secure-Flag
from flask import Flask, session
app = Flask(__name__)
app.secret_key = 'secret'
# Keine sichere Cookie-Konfiguration!
@app.route('/login')
def login():
session['user_id'] = user.id
# Cookie ohne Secure-Flag gesendet
return redirect('/dashboard')
# VERWUNDBAR: Manuelles Cookie ohne Secure
from flask import make_response
@app.route('/set-token')
def set_token():
response = make_response('Token gesetzt')
# Fehlendes Secure-Flag!
response.set_cookie('auth_token', token, httponly=True)
return response
// VERWUNDBAR: Servlet-Cookie ohne Secure
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Benutzer authentifizieren...
Cookie sessionCookie = new Cookie("SESSIONID", sessionId);
sessionCookie.setHttpOnly(true);
// Fehlt: sessionCookie.setSecure(true);
response.addCookie(sessionCookie);
response.sendRedirect("/dashboard");
}
}
// VERWUNDBAR: Spring-Session ohne sichere Cookies
@Configuration
public class SessionConfig {
// Keine Cookie-Konfiguration - Standards möglicherweise nicht sicher
}
// VERWUNDBAR: Express-Session ohne sicheres Cookie
const session = require('express-session');
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true
// Fehlt: secure: true
}
}));
// VERWUNDBAR: Manuelles Cookie ohne Secure-Flag
app.get('/set-cookie', (req, res) => {
res.cookie('authToken', token, {
httpOnly: true
// Fehlt: secure: true
});
res.send('Cookie gesetzt');
});
// VERWUNDBAR: PHP-Session ohne Secure-Flag
<?php
session_start(); // Verwendet Standardeinstellungen
$_SESSION['user_id'] = $user_id;
// VERWUNDBAR: setcookie ohne Secure
setcookie('auth_token', $token, [
'httponly' => true,
// 'secure' => true fehlt!
'path' => '/'
]);
?>
Lösungscode
# SICHER: Flask mit sicherer Cookie-Konfiguration
from flask import Flask, session
app = Flask(__name__)
app.secret_key = os.urandom(32)
# Sichere Cookies konfigurieren
app.config.update(
SESSION_COOKIE_SECURE=True, # Secure-Flag
SESSION_COOKIE_HTTPONLY=True, # HttpOnly-Flag
SESSION_COOKIE_SAMESITE='Lax', # SameSite-Attribut
SESSION_COOKIE_NAME='__Host-session' # Cookie-Präfix für extra Sicherheit
)
@app.route('/login')
def login():
session['user_id'] = user.id
# Cookie hat jetzt Secure-Flag
return redirect('/dashboard')
# SICHER: Manuelles Cookie mit allen Sicherheitsattributen
@app.route('/set-token')
def set_token():
response = make_response('Token gesetzt')
response.set_cookie(
'auth_token',
token,
secure=True, # Nur über HTTPS gesendet
httponly=True, # Nicht per JavaScript zugänglich
samesite='Strict', # Nicht in Cross-Site-Anfragen gesendet
max_age=3600, # 1 Stunde Ablauf
path='/'
)
return response
# SICHER: HTTPS und HSTS erzwingen
@app.before_request
def enforce_https():
if not request.is_secure and not app.debug:
return redirect(request.url.replace('http://', 'https://'), code=301)
@app.after_request
def add_security_headers(response):
# HSTS-Header - HTTPS für 1 Jahr erzwingen
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
return response
// SICHER: Servlet mit sicheren Cookies
@WebServlet("/login")
public class SecureLoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Benutzer authentifizieren...
Cookie sessionCookie = new Cookie("SESSIONID", sessionId);
sessionCookie.setSecure(true); // Nur HTTPS
sessionCookie.setHttpOnly(true); // Kein JavaScript-Zugriff
sessionCookie.setPath("/");
sessionCookie.setMaxAge(3600); // 1 Stunde
// SameSite erfordert Servlet 4.0+ oder Header-Manipulation
response.setHeader("Set-Cookie",
sessionCookie.getName() + "=" + sessionCookie.getValue() +
"; Secure; HttpOnly; SameSite=Strict; Path=/; Max-Age=3600");
response.sendRedirect("/dashboard");
}
}
// SICHER: Spring Security-Konfiguration
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest().requiresSecure() // HTTPS erzwingen
.and()
.headers()
.httpStrictTransportSecurity()
.includeSubDomains(true)
.maxAgeInSeconds(31536000);
}
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("SESSION");
serializer.setUseSecureCookie(true); // Secure-Flag
serializer.setUseHttpOnlyCookie(true); // HttpOnly-Flag
serializer.setSameSite("Strict"); // SameSite-Attribut
serializer.setCookiePath("/");
return serializer;
}
}
// SICHER: Spring Boot application.properties
// server.servlet.session.cookie.secure=true
// server.servlet.session.cookie.http-only=true
// server.servlet.session.cookie.same-site=strict
// SICHER: Express mit sicheren Session-Cookies
const session = require('express-session');
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
name: '__Host-sessionId', // Cookie-Präfix
cookie: {
secure: true, // Nur über HTTPS gesendet
httpOnly: true, // Nicht per JavaScript zugänglich
sameSite: 'strict', // Nicht in Cross-Site-Anfragen gesendet
maxAge: 3600000, // 1 Stunde
path: '/'
}
}));
// SICHER: Manuelles sicheres Cookie
app.get('/set-cookie', (req, res) => {
res.cookie('authToken', token, {
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: 3600000,
path: '/'
});
res.send('Cookie gesetzt');
});
// SICHER: HTTPS mit helmet erzwingen
const helmet = require('helmet');
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true
}));
// HTTP zu HTTPS umleiten
app.use((req, res, next) => {
if (!req.secure && req.get('x-forwarded-proto') !== 'https') {
return res.redirect(301, `https://${req.get('host')}${req.url}`);
}
next();
});
// SICHER: PHP mit sicheren Session-Cookies
<?php
// Session vor dem Start konfigurieren
ini_set('session.cookie_secure', 1); // Secure-Flag
ini_set('session.cookie_httponly', 1); // HttpOnly-Flag
ini_set('session.cookie_samesite', 'Strict'); // SameSite-Attribut
ini_set('session.use_only_cookies', 1); // Nur Cookies verwenden
ini_set('session.use_strict_mode', 1); // Strikter Session-Modus
session_start();
$_SESSION['user_id'] = $user_id;
// SICHER: Manuelles Cookie mit allen Attributen
setcookie('auth_token', $token, [
'expires' => time() + 3600,
'path' => '/',
'secure' => true, // Nur HTTPS
'httponly' => true, // Kein JavaScript
'samesite' => 'Strict' // Kein Cross-Site
]);
// Oder Header für volle Kontrolle verwenden
header('Set-Cookie: auth_token=' . $token . '; Secure; HttpOnly; SameSite=Strict; Path=/; Max-Age=3600');
?>
Ausgenutzt in der Praxis
Firesheep (2010)
Firesheep war eine Firefox-Erweiterung, die die Leichtigkeit des Session-Hijackings in unverschlüsselten WLAN-Netzwerken demonstrierte, indem Cookies ohne Secure-Flag von großen Sites wie Facebook und Twitter erfasst wurden.
SSL-Strip-Angriffe
Angreifer verwenden SSL-Stripping, um HTTPS-Verbindungen auf HTTP herabzustufen und Cookies zu erfassen, denen das Secure-Flag fehlt, selbst auf Sites, die normalerweise HTTPS verwenden.
Public-WLAN-Session-Hijacking
Zahlreiche reale Angriffe in öffentlichen WLAN-Netzwerken haben fehlende Secure-Flags ausgenutzt, um Session-Cookies von Bank-, E-Mail- und Social-Media-Sites zu stehlen.
Tools zum Testen/Ausnutzen
- Burp Suite — Cookie-Attribute analysieren
- OWASP ZAP — nach unsicheren Cookies scannen
- Browser DevTools — Cookie-Einstellungen inspizieren
- Wireshark — unverschlüsselten Cookie-Traffic erfassen
CVE-Beispiele
- CVE-2021-22893 — Pulse Secure Cookie-Schwachstelle
- CVE-2020-8945 — GPG Cookie-Sicherheitsproblem
- CVE-2019-5736 — Container-Cookie-Exposure
Referenzen
- MITRE. "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute." https://cwe.mitre.org/data/definitions/614.html
- OWASP. "Secure Cookie Attribute." https://owasp.org/www-community/controls/SecureCookieAttribute