Aktuálna situácia: PHP2Shell. Dve kritické zraniteľnosti PHP (CVSS 9.2) umožňujú spustenie škodlivého kódu bez prihlásenia. Záplaty od 21. 10. 2026.Čo treba urobiť teraz →

Zabezpečiť session v PHP: bezpečnosť session PHP v praxi

Session udržiavajú používateľov prihlásených, a sú preto lákavým cieľom. Ako bezpečne nastaviť cookies, ID session a miesta uloženia a uplatniť upozornenie PHP2Shell k upload progress.

Stav 5 min čítaniaPríručky

Stručne: Pre bezpečnosť session PHP sú rozhodujúce štyri veci: bezpečné nastavenia cookies, nové ID session po každom prihlásení, oddelené a chránené miesta uloženia a krátke doby platnosti. Kvôli PHP2Shell by malo byť navyše na strane servera nastavené session.upload_progress.enabled=0, kým nie je dôvod pre túto funkciu.

Prečo sú session lákavým cieľom

Session si pamätá, že používateľ je prihlásený. Technicky dostane prehliadač náhodné ID session v cookie a server ukladá príslušné údaje. Kto toto ID pozná, je pre aplikáciu tým istým používateľom, bez hesla a bez druhého faktora.

Pre prevádzkovateľov to znamená: slabá správa session môže vyradiť ochranu prihlásenia, aj keď sú heslá a dvojfaktorové prihlásenie čisto zavedené. Obzvlášť kritické je to v administrátorských oblastiach, zákazníckych účtoch a portáloch s osobnými údajmi.

Typickými rizikami sú získanie ID session (session hijacking), podsunutie známeho ID pred prihlásením (session fixation) a príliš dlho platné relácie na zdieľaných počítačoch.

Bezpečné základné nastavenia v php.ini

Najdôležitejšie hodnoty možno nastaviť centrálne v php.ini alebo pre každý web v poole FPM. V poole použite php_admin_value alebo php_admin_flag, aby ich aplikácia nemohla prepísať.

; Základné spevnenie session
session.use_strict_mode   = 1
session.use_only_cookies  = 1
session.use_trans_sid     = 0
session.cookie_httponly   = 1
session.cookie_secure     = 1
session.cookie_samesite   = "Lax"
session.cookie_lifetime   = 0
session.gc_maxlifetime    = 1800
session.name              = "APPSESSID"

; Upozornenie PHP2Shell od php.net, potom reštartovať všetkých workerov
session.upload_progress.enabled = 0

use_strict_mode zaisťuje, že PHP neprevezme neznáme ID zadané prehliadačom. cookie_httponly bráni tomu, aby JavaScript ID prečítal, čo obmedzuje následky Cross-Site-Scriptingu. cookie_secure posiela cookie iba cez HTTPS. SameSite=Lax sťažuje požiadavky medzi stránkami s platnou reláciou; pre čisto administrátorské oblasti sa môže hodiť Strict.

Doba platnosti 1 800 sekúnd je ukážková hodnota. Určite ju podľa potreby ochrany: kratšiu pre správu a zákaznícke údaje, dlhšiu iba tam, kde je to odborne potrebné.

Pamätajte, že gc_maxlifetime určuje iba to, odkedy smú byť staré údaje session zmazané. Na niektorých distribúciách nečistí súbory session samotné PHP, ale pravidelná systémová úloha. Skontrolujte potom, akú hodnotu táto úloha používa, aby vaše nastavenie skutočne zabralo. Pri odhlásení po nečinnosti sa navyše nespoliehajte iba na funkciu upratovania, ale kontrolujte čas poslednej akcie v samotnej aplikácii, ako ukazuje nasledujúca ukážka.

Obnoviť ID session po prihlásení

Najdôležitejším pravidlom v kóde je vytvoriť ID session nanovo pri každej zmene oprávnenia, teda pri prihlásení, pri prechode do administrátorského režimu a pri odhlásení. Nasledujúca ukážka zobrazuje čistý základný vzor s password_verify():

<?php
declare(strict_types=1);

session_start();

function anmelden(PDO $db, string $email, string $passwort): bool
{
    $stmt = $db->prepare('SELECT id, passwort_hash FROM benutzer WHERE email = :email');
    $stmt->execute(['email' => $email]);
    $nutzer = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$nutzer || !password_verify($passwort, $nutzer['passwort_hash'])) {
        return false; // rovnaké hlásenie pre nesprávnu adresu aj nesprávne heslo
    }

    session_regenerate_id(true);           // nové ID, staré zahodiť
    $_SESSION['benutzer_id']   = (int) $nutzer['id'];
    $_SESSION['letzte_aktion'] = time();
    return true;
}

function pruefeLeerlauf(int $sekunden = 900): void
{
    if (isset($_SESSION['letzte_aktion']) && time() - $_SESSION['letzte_aktion'] > $sekunden) {
        abmelden();
        return;
    }
    $_SESSION['letzte_aktion'] = time();
}

function abmelden(): void
{
    $_SESSION = [];
    $p = session_get_cookie_params();
    setcookie(session_name(), '', [
        'expires'  => time() - 3600,
        'path'     => $p['path'],
        'domain'   => $p['domain'],
        'secure'   => $p['secure'],
        'httponly' => $p['httponly'],
        'samesite' => $p['samesite'],
    ]);
    session_destroy();
}

Formuláre, ktoré niečo menia, navyše chráňte tokenom CSRF. Vytvára sa pomocou bin2hex(random_bytes(32)), ukladá sa do session a pri odoslaní sa porovnáva pomocou hash_equals().

Miesta uloženia a oddelenie klientov

Štandardne ukladá PHP session ako súbory do spoločného adresára. Na serveri s viacerými webmi to môže znamenať, že kompromitovaný web môže čítať session iného webu. Preto patrí ku každému webu samostatný pool so samostatným používateľom a samostatnou cestou pre session.

; v poole FPM príslušného webu
php_admin_value[session.save_path] = /var/lib/php/sessions/kunde-a

Adresár by mal patriť používateľovi poolu a mať práva 0700. Ako weby navyše navzájom odtienite, popisuje príručka open_basedir a izolácia každého webu. Ak sa session ukladajú do Redis alebo databázy, platia rovnaké zásady: samostatný prístup pre každú aplikáciu, žiadny otvorený sieťový prístup.

Bezpečnosť session PHP a PHP2Shell

Zraniteľnosti PHP2Shell CVE-2026-109618 a CVE-2026-109619 sú v samotnom PHP. Ako jedno z prechodných opatrení php.net uvádza nastaviť session.upload_progress.enabled=0 v php.ini, v poole FPM alebo v konfigurácii servera a potom reštartovať všetkých workerov. Výslovne nie cez ini_set() ani .user.ini.

Dňa 23. 10. 2026 nasledovalo upozornenie k CVE-2026-115560. Možné vykonanie kódu tam existuje iba pri nezvyčajnej kombinácii serializácie session, prestavenia cez ini_set() pred session_start() a aktívneho upload progress. Náprava je rovnaké nastavenie, do ďalšieho pravidelného vydania s opravami chýb.

Dôležité

Toto nastavenie je prechodné opatrenie a nie úplná ochrana. Rozhodujúca zostáva aktualizácia na opravenú verziu PHP a následný reštart všetkých workerov PHP.

Po zmene skontrolujte, ktorá hodnota skutočne platí. Príkazový riadok často zobrazuje inú konfiguráciu než webový server; vypovedajúca je chránená, potom opäť zmazaná kontrolná stránka alebo samotná konfigurácia poolu.

Typické chyby pri session v aplikáciách PHP

Mnohé zraniteľnosti nevznikajú chýbajúcimi nastaveniami, ale spôsobom, akým aplikácie session používajú. Tieto vzory by ste mali vo vlastnom kóde a u dodávateľov cielene zisťovať:

  • Príliš veľa v session: Heslá, úplné platobné údaje alebo veľké súbory údajov do session nepatria. Ukladajte iba to, čo je potrebné na priradenie, napríklad ID používateľa a roly.
  • Práva iba zo session: Kto je administrátor, by sa pri kritických akciách mal overovať voči databáze. Inak zostanú odobraté práva účinné až do uplynutia relácie.
  • ID session v adrese: ID v URL skončia v logoch, histórii prehliadača a údajoch referera. use_only_cookies a use_trans_sid = 0 tomu zabraňujú.
  • Žiadny koniec relácie: Ak chýba časový limit nečinnosti, administrátor na zdieľanom počítači zostáva prihlásený neobmedzene.
  • HTTPS za proxy nesprávne rozpoznané: Ak šifrovanie končí na load balanceri, musí to aplikácia vedieť. Inak môže nastavovať cookies bez príznaku Secure.

Po bezpečnostnom incidente patrí k veci aj zahodiť všetky existujúce session. Najjednoduchšie je to tak, že zmažete obsah adresára session alebo zmeníte názov session. Všetci používatelia sa potom musia prihlásiť znova a ukradnuté relácie sú bezcenné.

Ako konkrétne pomáha PHP SOS?

  • Kontrolujeme nastavenia session, príznaky cookies a miesta uloženia na všetkých weboch servera a dokumentujeme skutočne účinné hodnoty.
  • Prechodné opatrenia k PHP2Shell nastavujeme pre každý pool, workerov kontrolovane reštartujeme a výsledok dokladujeme.
  • Weby oddeľujeme samostatnými poolmi a cestami pre session v rámci spevnenia servera.
  • Pre vlastné vývoje kontrolujeme prihlásenie, odhlásenie a zmenu session v kóde a odporúčame konkrétne zmeny.

Časté otázky

Čo je session hijacking?

Pri session hijackingu útočník prevezme reláciu prihláseného používateľa tým, že získa jeho ID session. S ID je pre aplikáciu týmto používateľom, bez znalosti hesla. Bezpečné príznaky cookies a krátke doby platnosti to výrazne sťažujú.

Prečo sa musí ID session po prihlásení vytvoriť nanovo?

Ak ostane ID pred prihlásením a po ňom rovnaké, mohlo by vopred známe alebo podsunuté ID platiť aj po prihlásení. session_regenerate_id(true) vytvorí nové ID a staré zahodí.

Môžem session.upload_progress.enabled vypnúť cez ini_set()?

Nie, podľa php.net to nestačí. Nastavenie patrí do php.ini, poolu FPM alebo konfigurácie servera, nie do ini_set() ani .user.ini. Potom sa musia reštartovať všetci workeri PHP.

Kde by sa mali ukladať súbory session?

V adresári mimo webroot, ktorý smie čítať len používateľ príslušného poolu PHP. Na serveroch s viacerými webmi by mal mať každý web vlastný adresár pre session.

Zdroje

Okamžitý kontakt

Každá hodina sa počíta. Napíšte nám hneď.

Stručne opíšte systém, verziu PHP a svoje pozorovanie. Ozveme sa, vyjasníme situáciu a budeme pracovať na diaľku, kým nebude incident uzavretý a zdokumentovaný.

Okamžitá pomoc