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

Вградените функции за сигурност на PHP

PHP носи сигурни градивни елементи за пароли, случайни стойности, екраниране, криптография и сесии. Който ги използва последователно, избягва най-честите грешки в приложенията.

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

Накратко: За най-честите задачи по сигурността PHP носи готови, проверени функции: password_hash() за пароли, random_bytes() и random_int() за токени, htmlspecialchars() срещу cross-site scripting, подготвени заявки с PDO срещу SQL инжекция, hash_equals() за сигурни сравнения и разширението Sodium за криптография. Който използва последователно тези градивни елементи, избягва повечето пробиви в приложенията. Срещу грешки в самия интерпретатор на PHP, както при PHP2Shell, те не помагат; там помага само актуализацията.

Защо вградени функции за сигурност в PHP?

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

За вземащите решения това означава: питайте Вашата агенция или Вашия екип за разработка не дали функциите за сигурност са писани сами, а дали се използват стандартните функции на езика. Таблицата дава преглед.

Задача Функция Налична от Важна бележка
Съхраняване на пароли password_hash(), password_verify() PHP 5.5 колона до 255 знака; bcrypt съкращава до 72 байта
Случайни токени random_bytes(), random_int() PHP 7.0 никога rand() или mt_rand() за тайни
Случайност обектно-ориентирано Random\Randomizer PHP 8.2 същата сигурност, по-гъвкав интерфейс
Екраниране на HTML изход htmlspecialchars() открай време флаговете по подразбиране от 8.1 екранират и единични кавички
Сравнение с постоянно време hash_equals() PHP 5.6 въвеждането от потребителя като втори аргумент
Съвременна криптография Sodium (sodium_*) PHP 7.2 вместо собствено криптиране
Тайни в stack trace #[\SensitiveParameter] PHP 8.2 стойността не се появява в trace
Проверка на въвеждани данни filter_var() PHP 5.2 проверява формата, не замества екранирането

Пароли и токени

password_hash() създава осолен хеш, password_verify() го проверява. С PASSWORD_DEFAULT PHP използва в момента bcrypt; от PHP 8.4 коефициентът на разходите по подразбиране според ръководството е 12 вместо 10. Тъй като алгоритъмът по подразбиране може да се промени, ръководството препоръчва колона в базата данни с 255 знака. При bcrypt паролите се отрязват след 72 байта, което трябва да се има предвид при много дълги пропозиции за парола.

<?php
// Регистрация
$hash = password_hash($passwort, PASSWORD_DEFAULT);

// Вход, включително автоматично обновяване на стари хешове
if (password_verify($eingabe, $hash)) {
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $hash = password_hash($eingabe, PASSWORD_DEFAULT); // съхраняване наново
    }
}

// Токен за връзка за възстановяване на парола
$token = bin2hex(random_bytes(32));

За сравнения на тайни, например на подпис, трябва да се използва hash_equals(). Обикновеното сравнение с === според ръководството може да издаде чрез времето за изпълнение от кое място две стойности се различават. По-подробно: Сигурно съхраняване на пароли в PHP и сигурни случайни числа и токени.

Екраниране на изхода и сигурни заявки към базата данни

Cross-site scripting възниква, когато въвеждани от потребители данни попаднат нефилтрирани в HTML. htmlspecialchars() превръща специалните знаци в HTML ентитита. От PHP 8.1 флаговете по подразбиране са ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401; преди това единичните кавички не се преобразуваха. Който трябва да поддържа по-стари версии, задава флаговете изрично.

SQL инжекцията се предотвратява с подготвени заявки. Стойностите се предават отделно от SQL текста и не могат да променят заявката:

<?php
$stmt = $pdo->prepare('SELECT id, name FROM kunden WHERE email = :email');
$stmt->execute(['email' => $email]);
$kunde = $stmt->fetch();

echo htmlspecialchars($kunde['name'] ?? '', ENT_QUOTES, 'UTF-8');

Подробностите са в Предотвратяване на cross-site scripting в PHP и на страницата за SQL инжекция.

Проверката на въвеждани данни е втора, отделна стъпка. filter_var() установява дали една стойност има валиден формат, например имейл адрес или цяло число в разрешен диапазон. Това обаче не замества нито екранирането при изхода, нито подготвената заявка, защото и формално валидни стойности могат да съдържат специални знаци.

Тайните да не попадат в съобщенията за грешки

Подценявано изтичане на данни са stack trace. Ако във функция възникне грешка, PHP записва веригата от извиквания заедно с аргументите. Ако там има парола или API ключ, той попада в лога. От PHP 8.2 атрибутът #[\SensitiveParameter] отбелязва такива параметри; стойността им в trace се появява тогава само като обект SensitiveParameterValue.

<?php
function anmelden(string $benutzer, #[\SensitiveParameter] string $passwort): bool
{
    // ... проверка ...
    throw new RuntimeException('Datenbank nicht erreichbar');
}

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

Сесии: сигурни настройки и нови стандарти

Сесиите са често срещана цел на атаки. Три настройки са централни: session.use_strict_mode=1 отхвърля идентификатори на сесии, които сървърът не е създал сам; session.cookie_httponly=1 предотвратява достъпа до бисквитката на сесията чрез JavaScript; session.cookie_samesite=Lax затруднява изпращането ѝ към чужди сайтове. Според приетия RFC точно тези три стойности стават стандарт с PHP 8.6. Задайте ги сами дотогава, а и след това изрично, за да не зависи конфигурацията от стойността по подразбиране.

session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.cookie_secure = 1

Повече има в Защита на сесиите в PHP.

Какво вградените функции не постигат

Проектът PHP в политиката си за сигурност е ясен: PHP не е sandbox. Заобикалянето на open_basedir или disable_functions, злонамерените входни данни към unserialize() и непроверените аргументи към функции като mysqli_query() не се считат за уязвимости на PHP. За операторите това означава: тези настройки са полезно заздравяване, но не граница на сигурността, а unserialize() няма работа с чужди данни.

Втората точка засяга PHP2Shell. CVE-2026-109618 и CVE-2026-109619 според php.net позволяват изпълнение на код, преди или докато приложението Ви работи; при mod_php е показан експлойт, преди изобщо да се изпълни код на приложението. Никоя функция във Вашия код не може да го улови. Сигурното програмиране и актуалната версия на PHP са две отделни задължения и и двете трябва да бъдат изпълнени.

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

В одита на сигурността за PHP приложения проверяваме целенасочено:

  • Работа с пароли и токени: Използват ли се password_hash() и random_bytes(), или има собствени разработки?
  • Изходи и заявки: Къде въвежданите данни попадат нефилтрирани в HTML, SQL или команди на шела?
  • Конфигурация на сесиите: Зададени ли са Strict Mode, HttpOnly, SameSite и Secure и не могат ли да се презаписват?
  • Среда за изпълнение: Работи ли поддържана версия на PHP с корекциите от 21.10.2026 г.?

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

Как се съхраняват правилно паролите в PHP?

С password_hash() и PASSWORD_DEFAULT, а проверката е с password_verify(). Колоната в базата данни според ръководството трябва да побира до 255 знака, защото алгоритъмът по подразбиране може да се промени в бъдеще.

rand() подходящ ли е за токени?

Не. За токени, ключове и връзки за парола трябва да се използват random_bytes() или random_int(). Според ръководството те дават криптографски сигурни случайни стойности.

Откога Sodium е част от PHP?

Разширението Sodium за съвременна криптография е част от PHP от версия 7.2.0. По-старите версии можеха да го добавят само чрез PECL.

Тези функции защитават ли от PHP2Shell?

Не. Те защитават от грешки във Вашето приложение. PHP2Shell се намира в самия интерпретатор и се затваря само чрез актуализация на PHP, последвана от рестартиране на всички PHP процеси.

Променят ли се стандартите за сесии в PHP 8.6?

Да, според приетия RFC session.use_strict_mode и session.cookie_httponly се включват по подразбиране, а session.cookie_samesite се задава на Lax. Съществуващите конфигурации все пак трябва сами да зададете изрично.

Източници

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

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

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

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