# Relace a cookies v PHP

> Jak fungují relace (session) a cookies v PHP: ID relace, ukládání, výchozí hodnoty php.ini, průběh nahrávání a přechodné opatření k PHP2Shell.

Zdroj: https://phpsos.de/cs/php/sessions-und-cookies/  
Stav: 25.10.2026  
Poskytovatel: PHP SOS, Nouzová pomoc pro PHP a bezpečnost serverů. Okamžitá pomoc přes WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20den%2C%20PHP%20SOS%2C%20pot%C5%99ebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20PHP%20serverem.%20Firma%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručně:** HTTP si mezi dvěma požadavky nic nepamatuje. Relace PHP to řeší: PHP přidělí náhodné ID relace, pošle je prohlížeči jako cookie a příslušná data uloží na serveru, standardně jako soubor. Při každém dalším požadavku načte `session_start()` data podle ID zpět. K relaci PHP patří i funkce `session.upload_progress`, kterou php.net kvůli PHP2Shell doporučuje dočasně vypnout na straně serveru.

## Proč webové aplikace potřebují relace

Každý požadavek na webový server stojí sám o sobě. Bez doplňkového mechanismu by e-shop při kliknutí na „Košík“ nevěděl, kdo do něj právě něco vložil, a administrace by musela při každém kliknutí žádat heslo. Relace spojují jednotlivé požadavky do sezení.

Pro rozhodovatele to znamená: ID relace má po přihlášení stejnou hodnotu jako uživatelské jméno a heslo dohromady. Pro správce to znamená: kde a jak jsou data relací uložena, je bezpečnostní otázka, zvlášť na serverech s více weby.

## Co se děje při session_start()

Průběh je při každém požadavku stejný a lze jej popsat v pěti krocích:

1. Prohlížeč pošle s sebou cookie s názvem relace, standardně `PHPSESSID`.
2. `session_start()` přečte ID a předá je obslužnému programu úložiště, standardně `files`.
3. Obslužný program načte uložená data, PHP je pomocí `serialize_handler` převede zpět a naplní `$_SESSION`.
4. Skript čte a mění `$_SESSION` jako běžné pole.
5. Na konci požadavku PHP data zapíše zpět. S `session.lazy_write` (výchozí: zapnuto) jen tehdy, pokud se změnila.

```php
<?php
session_start();

$_SESSION['besuche'] = ($_SESSION['besuche'] ?? 0) + 1;
echo 'Seitenaufrufe in dieser Sitzung: ', (int) $_SESSION['besuche'];
```

Pokud relace ještě neexistuje, PHP vytvoří nové ID a nastaví cookie. Je-li aktivní `session.use_strict_mode`, PHP odmítne neznámá ID předaná prohlížečem a vytvoří nové. Příručka PHP toto nastavení označuje pro základní bezpečnost za nezbytné.

## Výchozí hodnoty, které je dobré znát

Následující hodnoty platí podle příručky PHP, pokud není nastaveno jinak. Mnoho distribucí a poskytovatelů hostingu nastavuje vlastní hodnoty, proto vždy rozhoduje skutečně účinná konfigurace.

| Nastavení | Výchozí | Význam |
|---|---|---|
| `session.save_handler` | `files` | místo uložení dat, možné i Redis nebo databáze |
| `session.name` | `PHPSESSID` | název cookie |
| `session.serialize_handler` | `php` | formát uložených dat |
| `session.use_strict_mode` | `0` | neznámá ID se přijímají |
| `session.use_only_cookies` | `1` | žádné ID relace v adrese |
| `session.cookie_httponly` | `0` | JavaScript může cookie číst |
| `session.cookie_secure` | `0` | cookie i přes nešifrované HTTP |
| `session.cookie_samesite` | prázdné | žádný atribut SameSite |
| `session.gc_maxlifetime` | `1440` | sekundy do možného úklidu |
| `session.gc_probability` / `gc_divisor` | `1` / `100` | úklid zhruba při každém stém spuštění |
| `session.upload_progress.enabled` | `1` | průběh nahrávání se zapisuje do relace |

Hodnoty `cookie_httponly`, `cookie_secure` a `use_strict_mode` tedy nejsou z výroby nastaveny z hlediska bezpečnosti. Jak je správně nastavit, popisuje průvodce [Zabezpečení relací v PHP](https://phpsos.de/cs/ratgeber/session-sicherheit-php/). Nastavení `session.sid_length` a `session.sid_bits_per_character` jsou od PHP 8.4.0 označena jako zastaralá.

## Přímé nastavování cookies

Vedle cookie relace může aplikace nastavovat vlastní cookies. Od PHP 7.3.0 přijímá `setcookie()` pro to pole voleb, včetně `samesite`. Od PHP 8.5.0 přibyla navíc volba `partitioned`.

```php
<?php
setcookie('sprache', 'de', [
    'expires'  => time() + 60 * 60 * 24 * 30,
    'path'     => '/',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);
```

Podle příručky musí být u `samesite` s hodnotou `None` nastaveno i `secure`, jinak prohlížeč cookie zablokuje. Cookies jsou data prohlížeče: jejich obsah se při dalším požadavku vrací přes `$_COOKIE` a je třeba jej ověřovat jako každý jiný vstup. Více na stránce [Superglobály](https://phpsos.de/cs/php/superglobals/).

## session.upload_progress: indikátor průběhu nahrávání

PHP může během nahrávání souboru zapisovat průběh do relace. Formulář k tomu posílá skryté pole s názvem z `session.upload_progress.name`, standardně `PHP_SESSION_UPLOAD_PROGRESS`. PHP pak ukládá data pod klíčem s předponou `upload_progress_` do `$_SESSION`, s údaji jako čas zahájení, celková velikost a již zpracované bajty.

Důležité pro porozumění: podle příručky zapisuje PHP tyto informace do relace dříve, než se spustí jakýkoli skript. Funkce tedy pracuje během zpracování požadavku, ještě před kódem aplikace. Její nastavení jsou typu `INI_PERDIR` a nelze je měnit za běhu.

## Relace a PHP2Shell: přechodné opatření

Jako jedno z přechodných opatření proti zranitelnostem PHP2Shell uvádí php.net nastavit `session.upload_progress.enabled=0` v php.ini, v poolu FPM nebo v konfiguraci serveru a poté restartovat všechny workery, výslovně nikoli přes `ini_set()` nebo `.user.ini`. Dne 23. 10. 2026 přibylo upozornění k [CVE-2026-115560](https://phpsos.de/cs/php2shell/cve-2026-115560/) se stejným nápravným opatřením do dalšího řádného bugfix vydání.

```ini
; Pool FPM webu, poté restartovat všechny workery
php_admin_flag[session.upload_progress.enabled] = off
```

Podle odborných zpráv toto nastavení samo o sobě neuzavře obě zranitelnosti. Povinná zůstává aktualizace na PHP 8.5.12, 8.4.27, 8.3.36 nebo 8.2.35. Zda vaše aplikace průběh nahrávání vůbec používá a jak nastavení trvale provést, popisuje článek [Vypnutí session.upload_progress](https://phpsos.de/cs/blog/session-upload-progress-abschalten/).

## Jak konkrétně pomáhá PHP SOS?

- Zjistíme skutečně účinná nastavení relací pro každý web, nejen hodnoty příkazové řádky.
- Nastavíme přechodná opatření k PHP2Shell pro každý pool, restartujeme všechny workery a ověříme výsledek.
- Místa uložení relací a uživatele poolů mezi weby oddělíme v rámci [zpevnění serveru](https://phpsos.de/cs/leistungen/server-haertung/).
- Po incidentu zneplatníme všechny existující relace, aby odcizená ID relací pozbyla hodnoty.


## Časté dotazy

**Jaký je rozdíl mezi cookie a relací (session)?**  
Cookie je malý datový záznam, který prohlížeč ukládá a posílá s každým požadavkem. Relace ukládá vlastní data na serveru; v cookie je jen náhodný identifikátor, ID relace.

**Jak dlouho žije relace PHP?**  
Cookie relace platí standardně do zavření prohlížeče. Data na serveru smějí být uklizena po session.gc_maxlifetime, standardně 1440 sekund bez přístupu. Kdy se to skutečně stane, závisí na logice úklidu systému.

**Co dělá session.upload_progress?**  
Funkce zapisuje během nahrávání souboru průběh do relace, aby jej mohl zobrazit druhý požadavek. Je standardně aktivní. Kvůli PHP2Shell php.net doporučuje ji dočasně vypnout na straně serveru.

**Stačí session.upload_progress vypnout přes ini_set()?**  
Ne. Nastavení lze podle příručky za běhu stejně změnit, a php.net výslovně uvádí php.ini, pool FPM nebo konfiguraci serveru jako správná místa, nikoli ini_set() nebo .user.ini. Poté restartovat všechny workery.

## Zdroje

- [Příručka PHP: Konfigurace relací](https://www.php.net/manual/de/session.configuration.php)
- [Příručka PHP: Průběh nahrávání v relaci](https://www.php.net/manual/de/session.upload-progress.php)
- [Příručka PHP: setcookie](https://www.php.net/manual/en/function.setcookie.php)
- [php.net: Bezpečnostní oznámení](https://www.php.net/)
