Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

Сесии и бисквитки (cookies) в PHP

Сесиите превръщат HTTP без състояние във влизане в системата, което се запазва през няколко страници. Тук е описано как PHP го решава вътрешно, кои са стандартните стойности и какво общо има session.upload_progress с PHP2Shell.

Актуалност 5 мин. четенеЗнания за PHP

Накратко: HTTP не запомня нищо между две заявки. PHP сесията решава това: PHP присвоява случаен ID на сесията, изпраща го като бисквитка на браузъра и съхранява принадлежащите данни на сървъра, по подразбиране като файл. При всяка следваща заявка session_start() чете данните отново по ID. Към PHP сесията спада и функцията session.upload_progress, която php.net заради PHP2Shell препоръчва временно да се изключи от страна на сървъра.

Защо уеб приложенията се нуждаят от сесии

Всяка заявка към уеб сървъра стои сама за себе си. Без допълнителен механизъм един магазин при клик върху „Количка“ нямаше да знае кой току-що е сложил нещо в нея, а административната зона би трябвало да пита за паролата при всеки клик. Сесиите свързват отделните заявки в една сесия.

За вземащите решения това означава: ID на сесията след влизането струва колкото потребителското име и паролата заедно. За администраторите това означава: къде и как лежат данните на сесията, е въпрос на сигурност, особено на сървъри с няколко уебсайта.

Какво се случва при session_start()

Процесът е еднакъв при всяка заявка и може да се опише в пет стъпки:

  1. Браузърът изпраща бисквитката с името на сесията, по подразбиране PHPSESSID.
  2. session_start() чете ID и го предава на обработчика за съхранение, по подразбиране files.
  3. Обработчикът зарежда запазените данни, PHP ги преобразува обратно със serialize_handler и запълва $_SESSION.
  4. Скриптът чете и променя $_SESSION като обикновен масив.
  5. В края на заявката PHP записва данните обратно. С session.lazy_write (по подразбиране: включен) само ако са се променили.
<?php
session_start();

$_SESSION['besuche'] = ($_SESSION['besuche'] ?? 0) + 1;
echo 'Seitenaufrufe in dieser Sitzung: ', (int) $_SESSION['besuche'];

Ако още няма сесия, PHP създава ново ID и задава бисквитката. Ако session.use_strict_mode е активен, PHP отхвърля зададени от браузъра неизвестни ID и създава ново. Ръководството на PHP определя тази настройка като задължителна за основната сигурност.

Стандартни стойности, които трябва да се знаят

Следните стойности важат според ръководството на PHP, когато не е конфигурирано друго. Много дистрибуции и хостинг доставчици задават собствени стойности, затова винаги значение има действително ефективната конфигурация.

Настройка По подразбиране Значение
session.save_handler files място за съхранение на данните, възможни са и Redis или база данни
session.name PHPSESSID име на бисквитката
session.serialize_handler php формат на запазените данни
session.use_strict_mode 0 неизвестните ID се приемат
session.use_only_cookies 1 няма ID на сесията в адреса
session.cookie_httponly 0 JavaScript може да чете бисквитката
session.cookie_secure 0 бисквитка и през некриптиран HTTP
session.cookie_samesite празно без атрибут SameSite
session.gc_maxlifetime 1440 секунди до възможното почистване
session.gc_probability / gc_divisor 1 / 100 почистване приблизително при всяко стотно стартиране
session.upload_progress.enabled 1 напредъкът на качването се записва в сесията

Стойностите за cookie_httponly, cookie_secure и use_strict_mode от завода не са съобразени със сигурността. Как да ги зададете правилно, описва наръчникът Защита на сесиите в PHP. Настройките session.sid_length и session.sid_bits_per_character са отбелязани като остарели от PHP 8.4.0.

Директно задаване на бисквитки

Освен бисквитката на сесията едно приложение може да задава собствени бисквитки. От PHP 7.3.0 setcookie() приема за целта масив с опции, включително samesite. От PHP 8.5.0 има допълнително опцията partitioned.

<?php
setcookie('sprache', 'de', [
    'expires'  => time() + 60 * 60 * 24 * 30,
    'path'     => '/',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);

Според ръководството при samesite със стойност None трябва да е зададено и secure, иначе браузърът блокира бисквитката. Бисквитките са данни на браузъра: тяхното съдържание се връща при следващата заявка през $_COOKIE и трябва да се проверява като всеки друг вход. Повече по темата на страницата Суперглобални променливи.

session.upload_progress: индикатор за напредъка на качванията

PHP може по време на качване на файл да записва напредъка в сесията. За целта формулярът изпраща скрито поле с името от session.upload_progress.name, по подразбиране PHP_SESSION_UPLOAD_PROGRESS. PHP тогава поставя данните в $_SESSION под ключ с префикс upload_progress_, с данни като начален час, общ размер и вече обработени байтове.

Важно за разбирането: според ръководството PHP записва тази информация в сесията, преди да се изпълни какъвто и да е скрипт. Функцията следователно работи по време на обработката на заявката, още преди кода на приложението. Нейните настройки са от тип INI_PERDIR и не могат да се променят по време на изпълнение.

Сесии и PHP2Shell: временната мярка

Като една от временните мерки срещу уязвимостите на PHP2Shell php.net назовава задаването на session.upload_progress.enabled=0 в php.ini, във FPM пула или в конфигурацията на сървъра и след това рестартиране на всички работни процеси, изрично не чрез ini_set() или .user.ini. На 23.10.2026 г. се добави указанието за CVE-2026-115560, със същата мярка до следващото редовно издание с поправки.

; FPM пул на уебсайта, след това рестартирайте всички работни процеси
php_admin_flag[session.upload_progress.enabled] = off

Според специализирани доклади тази настройка сама не затваря двете уязвимости. Задължителна остава актуализацията до PHP 8.5.12, 8.4.27, 8.3.36 или 8.2.35. Дали Вашето приложение изобщо използва напредъка на качването и как да зададете настройката трайно, описва статията Изключване на session.upload_progress.

Как помага PHP SOS конкретно?

  • Четем действително ефективните настройки на сесиите за всеки уебсайт, а не само стойностите на командния ред.
  • Задаваме временните мерки за PHP2Shell за всеки пул, рестартираме всички работни процеси и проверяваме резултата.
  • Разделяме местата за съхранение на сесиите и потребителите на пуловете между уебсайтовете в рамките на заздравяването на сървъра.
  • След инцидент отхвърляме всички съществуващи сесии, така че откраднатите ID на сесии да станат безполезни.

Често задавани въпроси

Каква е разликата между бисквитка и сесия?

Бисквитката е малък запис, който браузърът съхранява и изпраща с всяка заявка. Сесията съхранява същинските данни на сървъра; в бисквитката стои само случаен идентификатор, ID на сесията.

Колко дълго живее една PHP сесия?

Бисквитката на сесията по подразбиране важи, докато браузърът не бъде затворен. Данните на сървъра могат да бъдат почистени след session.gc_maxlifetime, по подразбиране 1440 секунди без достъп. Кога това действително се случва, зависи от логиката за почистване на системата.

Какво прави session.upload_progress?

Функцията записва по време на качване на файл напредъка в сесията, за да може втора заявка да го показва. По подразбиране е активна. Заради PHP2Shell php.net препоръчва временно да се изключи от страна на сървъра.

Достатъчно ли е да изключа session.upload_progress чрез ini_set()?

Не. Настройката според ръководството така или иначе не може да се променя по време на изпълнение, а php.net изрично назовава php.ini, FPM пула или конфигурацията на сървъра като правилни места, а не ini_set() или .user.ini. След това рестартирайте всички работни процеси.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ