# Sesje i cookies w PHP

> Jak działają sesje i cookies w PHP: ID sesji, przechowywanie, wartości domyślne php.ini, postęp przesyłania plików i środek przejściowy przeciw PHP2Shell.

Źródło: https://phpsos.de/pl/php/sessions-und-cookies/  
Stan: 25.10.2026  
Dostawca: PHP SOS, Pomoc awaryjna PHP i bezpieczeństwo serwerów. Natychmiastowa pomoc przez WhatsApp: https://wa.me/491736494914?text=Dzie%C5%84%20dobry%2C%20PHP%20SOS%2C%20potrzebujemy%20pomocy%20z%20naszym%20serwerem%20PHP.%20Firma%3A%20%E2%80%A6%20Strona%20internetowa%3A%20%E2%80%A6

**Krótko:** HTTP nie pamięta niczego między dwoma żądaniami. Sesja PHP rozwiązuje ten problem: PHP nadaje losowe ID sesji, wysyła je jako cookie do przeglądarki i zapisuje powiązane dane na serwerze, domyślnie jako plik. Przy każdym kolejnym żądaniu `session_start()` odczytuje dane ponownie na podstawie ID. Do sesji PHP należy także funkcja `session.upload_progress`, którą php.net z powodu PHP2Shell zaleca tymczasowo wyłączyć po stronie serwera.

## Dlaczego aplikacje internetowe potrzebują sesji

Każde żądanie do serwera WWW stoi samo za siebie. Bez dodatkowego mechanizmu sklep nie wiedziałby po kliknięciu „Koszyk”, kto przed chwilą coś do niego włożył, a obszar administracyjny musiałby przy każdym kliknięciu pytać o hasło. Sesje łączą pojedyncze żądania w jedną sesję.

Dla osób podejmujących decyzje oznacza to: ID sesji jest po zalogowaniu tyle warte, co nazwa użytkownika i hasło razem. Dla administratorów oznacza to: gdzie i jak leżą dane sesji, to kwestia bezpieczeństwa, zwłaszcza na serwerach z wieloma stronami.

## Co dzieje się przy session_start()

Przebieg jest przy każdym żądaniu taki sam i można go opisać w pięciu krokach:

1. Przeglądarka wysyła cookie z nazwą sesji, domyślnie `PHPSESSID`.
2. `session_start()` odczytuje ID i przekazuje je obsłudze przechowywania, domyślnie `files`.
3. Obsługa ładuje zapisane dane, PHP przekształca je z powrotem przez `serialize_handler` i wypełnia `$_SESSION`.
4. Skrypt czyta i zmienia `$_SESSION` jak zwykłą tablicę.
5. Na końcu żądania PHP zapisuje dane z powrotem. Przy `session.lazy_write` (domyślnie: włączone) tylko wtedy, gdy się zmieniły.

```php
<?php
session_start();

$_SESSION['besuche'] = ($_SESSION['besuche'] ?? 0) + 1;
echo 'Seitenaufrufe in dieser Sitzung: ', (int) $_SESSION['besuche'];
```

Jeśli sesji jeszcze nie ma, PHP tworzy nowe ID i ustawia cookie. Jeśli `session.use_strict_mode` jest aktywne, PHP odrzuca nieznane ID narzucone przez przeglądarkę i tworzy nowe. Podręcznik PHP określa to ustawienie dla podstawowego bezpieczeństwa jako obowiązkowe.

## Wartości domyślne, które warto znać

Poniższe wartości obowiązują według podręcznika PHP, jeśli nie skonfigurowano inaczej. Wiele dystrybucji i dostawców hostingu ustawia własne wartości, dlatego zawsze liczy się faktycznie obowiązująca konfiguracja.

| Ustawienie | Domyślnie | Znaczenie |
|---|---|---|
| `session.save_handler` | `files` | miejsce zapisu danych, możliwe także Redis lub baza danych |
| `session.name` | `PHPSESSID` | nazwa cookie |
| `session.serialize_handler` | `php` | format zapisanych danych |
| `session.use_strict_mode` | `0` | nieznane ID są przyjmowane |
| `session.use_only_cookies` | `1` | brak ID sesji w adresie |
| `session.cookie_httponly` | `0` | JavaScript może odczytać cookie |
| `session.cookie_secure` | `0` | cookie także przez nieszyfrowane HTTP |
| `session.cookie_samesite` | puste | brak atrybutu SameSite |
| `session.gc_maxlifetime` | `1440` | sekundy do możliwego sprzątania |
| `session.gc_probability` / `gc_divisor` | `1` / `100` | sprzątanie mniej więcej przy co setnym starcie |
| `session.upload_progress.enabled` | `1` | postęp przesyłania jest zapisywany w sesji |

Wartości `cookie_httponly`, `cookie_secure` i `use_strict_mode` nie są więc fabrycznie nastawione na bezpieczeństwo. Jak je prawidłowo ustawić, opisuje poradnik [Zabezpieczanie sesji w PHP](https://phpsos.de/pl/ratgeber/session-sicherheit-php/). Ustawienia `session.sid_length` i `session.sid_bits_per_character` są od PHP 8.4.0 oznaczone jako przestarzałe.

## Bezpośrednie ustawianie cookies

Oprócz cookie sesji aplikacja może ustawiać własne cookies. Od PHP 7.3.0 `setcookie()` przyjmuje w tym celu tablicę z opcjami, w tym `samesite`. Od PHP 8.5.0 dochodzi dodatkowo opcja `partitioned`.

```php
<?php
setcookie('sprache', 'de', [
    'expires'  => time() + 60 * 60 * 24 * 30,
    'path'     => '/',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);
```

Według podręcznika przy `samesite` równym `None` musi być ustawione także `secure`, w przeciwnym razie przeglądarka blokuje cookie. Cookies to dane przeglądarki: ich zawartość wraca przy następnym żądaniu przez `$_COOKIE` i musi być sprawdzana jak każde inne dane wejściowe. Więcej na stronie [Superglobals](https://phpsos.de/pl/php/superglobals/).

## session.upload_progress: wskaźnik postępu przesyłania

PHP może w czasie przesyłania pliku zapisywać postęp w sesji. W tym celu formularz wysyła ukryte pole o nazwie z `session.upload_progress.name`, domyślnie `PHP_SESSION_UPLOAD_PROGRESS`. PHP zapisuje wtedy dane w `$_SESSION` pod kluczem z prefiksem `upload_progress_`, z informacjami takimi jak czas startu, rozmiar całkowity i liczba już przetworzonych bajtów.

Ważne dla zrozumienia: według podręcznika PHP zapisuje te informacje w sesji, zanim zostanie wykonany jakikolwiek skrypt. Funkcja działa więc podczas przetwarzania żądania, jeszcze przed kodem aplikacji. Jej ustawienia są typu `INI_PERDIR` i nie da się ich zmienić w czasie działania.

## Sesje i PHP2Shell: środek przejściowy

Jako jeden ze środków przejściowych przeciw lukom PHP2Shell php.net podaje ustawienie `session.upload_progress.enabled=0` w php.ini, w puli FPM lub w konfiguracji serwera, a następnie restart wszystkich workerów, wyraźnie nie przez `ini_set()` ani `.user.ini`. W dniu 23.10.2026 doszła wskazówka dotycząca [CVE-2026-115560](https://phpsos.de/pl/php2shell/cve-2026-115560/), z tym samym środkiem zaradczym do następnego regularnego wydania poprawkowego.

```ini
; Pula FPM strony, potem zrestartować wszystkie workery
php_admin_flag[session.upload_progress.enabled] = off
```

Według doniesień branżowych samo to ustawienie nie zamyka obu luk. Obowiązkowa pozostaje aktualizacja do PHP 8.5.12, 8.4.27, 8.3.36 lub 8.2.35. To, czy Państwa aplikacja w ogóle używa postępu przesyłania i jak ustawić to trwale, opisuje artykuł [Wyłączanie session.upload_progress](https://phpsos.de/pl/blog/session-upload-progress-abschalten/).

## Jak konkretnie pomaga PHP SOS?

- Odczytujemy faktycznie obowiązujące ustawienia sesji dla każdej strony, a nie tylko wartości wiersza poleceń.
- Ustawiamy środki przejściowe PHP2Shell dla każdej puli, restartujemy wszystkie workery i sprawdzamy wynik.
- Rozdzielamy miejsca przechowywania sesji i użytkowników pul między stronami w ramach [utwardzania serwera](https://phpsos.de/pl/leistungen/server-haertung/).
- Po incydencie unieważniamy wszystkie istniejące sesje, aby skradzione ID sesji straciły wartość.


## Częste pytania

**Jaka jest różnica między cookie a sesją?**  
Cookie to mały zestaw danych, który przeglądarka zapisuje i wysyła przy każdym żądaniu. Sesja przechowuje właściwe dane na serwerze; w cookie znajduje się tylko losowy identyfikator, czyli ID sesji.

**Jak długo żyje sesja PHP?**  
Cookie sesji obowiązuje domyślnie do zamknięcia przeglądarki. Dane na serwerze mogą być sprzątane po session.gc_maxlifetime, domyślnie po 1440 sekundach bez dostępu. To, kiedy faktycznie się to dzieje, zależy od logiki sprzątania w systemie.

**Co robi session.upload_progress?**  
Funkcja zapisuje w czasie przesyłania pliku postęp w sesji, aby drugie żądanie mogło go wyświetlić. Jest domyślnie aktywna. Z powodu PHP2Shell php.net zaleca tymczasowo wyłączyć ją po stronie serwera.

**Czy wystarczy wyłączyć session.upload_progress przez ini_set()?**  
Nie. Ustawienia tego według podręcznika i tak nie da się zmienić w czasie działania, a php.net wyraźnie wymienia jako właściwe miejsca php.ini, pulę FPM lub konfigurację serwera, a nie ini_set() czy .user.ini. Potem zrestartować wszystkie workery.

## Źródła

- [Podręcznik PHP: konfiguracja sesji](https://www.php.net/manual/de/session.configuration.php)
- [Podręcznik PHP: postęp przesyłania w sesji](https://www.php.net/manual/de/session.upload-progress.php)
- [Podręcznik PHP: setcookie](https://www.php.net/manual/en/function.setcookie.php)
- [php.net: komunikaty o bezpieczeństwie](https://www.php.net/)
