Skip to content

Bezpieczeństwo ciasteczek

Ciasteczka (cookies) przechowują dane sesji, tokeny uwierzytelnienia, preferencje użytkownika i identyfikatory śledzenia. Niepoprawnie skonfigurowane ciasteczko to jeden z najczęstszych wektorów ataków na aplikacje webowe — przechwycenie sesji, kradzież tokenu przez XSS czy fałszowanie żądań cross-site (CSRF).

Atrybuty bezpieczeństwa ciasteczek to flagi dodawane do nagłówka Set-Cookie, które instruują przeglądarkę jak ma się zachować z danym ciasteczkiem. W przeciwieństwie do nagłówków bezpieczeństwa HTTP, nie jest to osobny nagłówek — to część deklaracji każdego ciasteczka.

Przegląd atrybutów

AtrybutCo robi
SecureCiasteczko wysyłane tylko przez HTTPS
HttpOnlyCiasteczko niedostępne dla JavaScript
SameSite=StrictCiasteczko wysyłane tylko przy żądaniach z tej samej domeny
SameSite=LaxCiasteczko wysyłane przy nawigacji do strony, blokuje POST cross-site
SameSite=NoneCiasteczko wysyłane zawsze (wymaga Secure)
Max-AgeCzas ważności w sekundach
ExpiresData wygaśnięcia

Atrybut Secure

Oznacza, że ciasteczko może być wysyłane wyłącznie przez szyfrowane połączenie HTTPS. Przeglądarka nie wyśle go przy żądaniach HTTP.

Chroni przed przechwyceniem ciasteczka przez atakującego podsłuchującego ruch sieciowy (man-in-the-middle), np. w niezabezpieczonych sieciach Wi-Fi.

http
Set-Cookie: session_id=abc123; Secure

⚠️ Secure nie szyfruje treści ciasteczka

Atrybut Secure zapewnia tylko, że ciasteczko jest przesyłane przez zaszyfrowany kanał. Wartość ciasteczka nadal jest widoczna w przeglądarce (DevTools → Application → Cookies). Nie przechowuj wrażliwych danych wprost w ciasteczkach — używaj ich jako identyfikatorów sesji odwołujących się do danych po stronie serwera.


Atrybut HttpOnly

Uniemożliwia dostęp do ciasteczka przez JavaScript — document.cookie nie zwróci jego wartości, żaden skrypt nie może go odczytać ani zmodyfikować.

Chroni przed atakami XSS (Cross-Site Scripting), gdzie złośliwy skrypt wstrzyknięty w stronę próbuje wykraść ciasteczka sesji.

http
Set-Cookie: session_id=abc123; HttpOnly

💡 HttpOnly dla ciasteczek sesji

Ciasteczka przechowujące identyfikatory sesji, tokeny uwierzytelnienia i CSRF tokeny powinny zawsze mieć atrybut HttpOnly. JavaScript nie musi znać wartości sesji — ta informacja należy do serwera.


Atrybut SameSite

Kontroluje, czy ciasteczko jest wysyłane w żądaniach cross-site — czyli gdy żądanie pochodzi z innej domeny niż ta, dla której ciasteczko zostało ustawione. Chroni przed atakami CSRF (Cross-Site Request Forgery).

Wartości

  • Strict — ciasteczko wysyłane tylko gdy użytkownik jest już na twojej stronie. Żądania z zewnętrznych linków (np. kliknięcie linku w e-mailu) nie będą zawierać tego ciasteczka.
  • Lax — ciasteczko wysyłane przy nawigacji do strony (kliknięcie linku, wejście przez pasek adresu), ale nie przy żądaniach POST z innych domen. Dobry kompromis między bezpieczeństwem a użytecznością.
  • None — ciasteczko wysyłane zawsze, bez ograniczeń. Wymaga jednoczesnego atrybutu Secure.
http
Set-Cookie: session_id=abc123; SameSite=Lax; Secure
Set-Cookie: embed_token=xyz; SameSite=None; Secure

INFO

Od 2020 roku większość przeglądarek traktuje ciasteczka bez atrybutu SameSite jak SameSite=Lax. Starsze przeglądarki mogą zachowywać się inaczej — jawne ustawienie atrybutu eliminuje to ryzyko.


Czas ważności: Max-Age i Expires

Ciasteczka bez atrybutu Max-Age ani Expires to ciasteczka sesyjne — wygasają gdy użytkownik zamknie przeglądarkę. Ciasteczka z czasem ważności są zapisywane na dysku i przeżywają restart przeglądarki.

  • Max-Age — czas w sekundach od momentu ustawienia ciasteczka
  • Expires — konkretna data wygaśnięcia w formacie HTTP
http
Set-Cookie: pref=dark; Max-Age=2592000; Secure; HttpOnly
Set-Cookie: remember_me=token; Expires=Thu, 01 Jan 2026 00:00:00 GMT; Secure; HttpOnly

Krótki czas ważności ogranicza okno nadużycia w przypadku przechwycenia ciasteczka. Ciasteczka sesyjne są bezpieczniejsze niż długowieczne — rozważ czy trwałość jest naprawdę potrzebna.


Prefiksy bezpieczeństwa: __Secure- i __Host-

Prefiksy w nazwie ciasteczka to dodatkowy mechanizm wymuszania określonych atrybutów — przeglądarka odmówi ustawienia ciasteczka jeśli warunki nie są spełnione.

  • __Secure- — wymaga atrybutu Secure i wysłania przez HTTPS
  • __Host- — wymaga Secure, braku atrybutu Domain i Path=/ (ciasteczko przypisane wyłącznie do hosta, nie do subdomeny)
http
Set-Cookie: __Secure-session=abc123; Secure; HttpOnly; SameSite=Lax
Set-Cookie: __Host-token=xyz789; Secure; HttpOnly; SameSite=Strict; Path=/

💡 Kiedy używać prefiksów

Prefiksy są szczególnie wartościowe dla ciasteczek uwierzytelniających — eliminują możliwość podmienienia ciasteczka przez subdomenę lub przez HTTP. Używaj __Host- dla tokenów sesji gdy nie potrzebujesz współdzielenia ciasteczka między subdomenami.


Pełny przykład

Zalecana konfiguracja dla ciasteczka sesji:

http
Set-Cookie: __Host-session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/; Max-Age=3600

Jak ustawić atrybuty w PHP i WordPress

PHP

php
setcookie(
    '__Host-session',
    $value,
    [
        'expires'  => time() + 3600,
        'path'     => '/',
        'secure'   => true,
        'httponly' => true,
        'samesite' => 'Lax',
    ]
);

Dostępny od WordPress 6.2, pozwala modyfikować atrybuty ciasteczek logowania:

php
add_filter( 'wp_cookie_params', function( $params ) {
    $params['samesite'] = 'Lax';
    $params['secure']   = true;
    return $params;
} );

Kod dodaj do pliku functions.php aktywnego motywu lub przez wtyczkę do zarządzania snippetami.

WordPress — domyślne ciasteczka sesji

WordPress domyślnie ustawia HttpOnly dla ciasteczek uwierzytelniających (wordpress_logged_in_*, wordpress_sec_*). Atrybut Secure jest ustawiany automatycznie gdy strona działa przez HTTPS. Aby mieć pewność, dodaj do wp-config.php:

php
define( 'FORCE_SSL_ADMIN', true );

⚠️ Wymagane HTTPS

Atrybuty Secure i __Host- działają tylko przez HTTPS. Na stronie bez certyfikatu SSL przeglądarka ciche odrzuci takie ciasteczka. Certyfikat SSL na hostingu Joton możesz aktywować bezpłatnie przez Let's Encrypt — szczegóły w panelu administracyjnym.


Jak sprawdzić atrybuty ciasteczek

Narzędzia deweloperskie przeglądarki

W Chrome lub Firefox: DevTools → zakładka Application (Chrome) lub Storage (Firefox) → Cookies → wybierz domenę. Kolumny Secure, HttpOnly, SameSite pokazują bieżące atrybuty każdego ciasteczka.

Terminal

bash
curl -sI https://twojadomena.pl | grep -i set-cookie

Najczęstsze problemy

Ciasteczko z Secure nie jest ustawiane na lokalnym środowisku

Secure wymaga HTTPS. Na localhost bez certyfikatu SSL ciasteczko z tym atrybutem zostanie cicho odrzucone przez przeglądarkę. Podczas developmentu albo pomiń atrybut Secure lokalnie, albo użyj mkcert do utworzenia lokalnego certyfikatu.

WordPress traci sesję po ustawieniu SameSite=Strict

Logowanie przez zewnętrzne formularze lub przekierowania OAuth mogą przestać działać — żądanie POST z zewnętrznej domeny nie przeniesie ciasteczka sesji. Zmień na SameSite=Lax.

Wtyczki płatności przestały działać po zmianie atrybutów

Bramki płatności często wymagają ciasteczek cross-site dla iframe'ów z formularzem płatności. Dla takich ciasteczek ustaw SameSite=None; Secure. Nie modyfikuj bezpośrednio ciasteczek bramek płatności — zmieniaj tylko własne ciasteczka sesji.

Prefiks __Host- nie działa

Ciasteczko z prefiksem __Host- musi spełniać wszystkie cztery warunki jednocześnie: atrybut Secure, brak atrybutu Domain, Path=/ i wysyłanie przez HTTPS. Brak któregokolwiek z nich powoduje ciche odrzucenie ciasteczka przez przeglądarkę bez żadnego komunikatu błędu.


Przydatne linki