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

AuswirkungDetails
VertraulichkeitBereich: Session-Diebstahl

Session-Cookies, die über HTTP übertragen werden, können abgefangen werden und ermöglichen Session-Hijacking.
ZugriffskontrolleBereich: Kontoübernahme

Gestohlene Authentifizierungs-Cookies ermöglichen Angreifern, Benutzer zu imitieren.
IntegritätBereich: 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

  1. MITRE. "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute." https://cwe.mitre.org/data/definitions/614.html
  2. OWASP. "Secure Cookie Attribute." https://owasp.org/www-community/controls/SecureCookieAttribute