Aktualna sytuacja: PHP2Shell. Dwie krytyczne luki w PHP (CVSS 9,2) umożliwiają wykonanie złośliwego kodu bez logowania. Poprawki od 21.10.2026.Co należy teraz zrobić →

Wbudowane funkcje bezpieczeństwa PHP

PHP dostarcza bezpieczne elementy dla haseł, wartości losowych, maskowania, kryptografii i sesji. Kto konsekwentnie z nich korzysta, unika najczęstszych błędów aplikacji.

Stan 5 min czytaniaWiedza o PHP

Krótko: PHP dostarcza gotowe, sprawdzone funkcje do najczęstszych zadań bezpieczeństwa: password_hash() dla haseł, random_bytes() i random_int() dla tokenów, htmlspecialchars() przeciw cross-site scriptingowi, przygotowane zapytania z PDO przeciw SQL injection, hash_equals() dla bezpiecznych porównań i rozszerzenie Sodium dla kryptografii. Kto konsekwentnie używa tych elementów, unika większości luk w aplikacjach. Przed błędami w samym interpreterze PHP, jak w PHP2Shell, nie chronią; tam pomaga tylko aktualizacja.

Dlaczego wbudowane funkcje bezpieczeństwa PHP?

Samodzielne pisanie kodu bezpieczeństwa jest podatne na błędy. Własny hash hasła, samodzielnie zbudowany generator tokenów albo własny filtr dla danych wyjściowych HTML często wyglądają poprawnie, a mimo to nie są. Wbudowane funkcje są udokumentowane, przetestowane i utrzymywane wraz z aktualizacjami PHP.

Dla osób podejmujących decyzje oznacza to: niech Państwo nie pytają agencji ani zespołu deweloperskiego, czy funkcje bezpieczeństwa zbudowano samodzielnie, lecz czy używane są standardowe funkcje języka. Tabela daje przegląd.

Zadanie Funkcja Dostępna od Ważna uwaga
Przechowywanie haseł password_hash(), password_verify() PHP 5.5 kolumna do 255 znaków; bcrypt ucina do 72 bajtów
Losowe tokeny random_bytes(), random_int() PHP 7.0 nigdy rand() ani mt_rand() dla sekretów
Losowość obiektowo Random\Randomizer PHP 8.2 to samo bezpieczeństwo, elastyczniejszy interfejs
Maskowanie wyjścia HTML htmlspecialchars() od zawsze domyślne flagi od 8.1 maskują także apostrofy
Porównanie w stałym czasie hash_equals() PHP 5.6 dane od użytkownika jako drugi argument
Nowoczesna kryptografia Sodium (sodium_*) PHP 7.2 zamiast własnego szyfrowania
Sekrety w stacktrace #[\SensitiveParameter] PHP 8.2 wartość nie pojawia się w trace
Sprawdzanie danych wejściowych filter_var() PHP 5.2 sprawdza format, nie zastępuje maskowania

Hasła i tokeny

password_hash() tworzy zasolony hash, password_verify() go sprawdza. Z PASSWORD_DEFAULT PHP używa obecnie bcrypt; od PHP 8.4 domyślny współczynnik kosztu wynosi według podręcznika 12 zamiast 10. Ponieważ domyślny algorytm może się zmienić, podręcznik zaleca kolumnę w bazie danych na 255 znaków. W bcrypt hasła są ucinane po 72 bajtach, co trzeba uwzględnić przy bardzo długich frazach.

<?php
// Rejestracja
$hash = password_hash($passwort, PASSWORD_DEFAULT);

// Logowanie, z automatycznym uaktualnieniem starych hashy
if (password_verify($eingabe, $hash)) {
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $hash = password_hash($eingabe, PASSWORD_DEFAULT); // zapisać na nowo
    }
}

// Token dla linku do resetu hasła
$token = bin2hex(random_bytes(32));

Do porównywania sekretów, na przykład podpisu, należy używać hash_equals(). Zwykłe porównanie z === może według podręcznika zdradzić przez czas działania, od którego miejsca dwie wartości się różnią. Szerzej: Bezpieczne przechowywanie haseł w PHP oraz bezpieczne liczby losowe i tokeny.

Maskowanie wyjścia i bezpieczne zapytania do bazy danych

Cross-site scripting powstaje, gdy dane od użytkownika trafiają do HTML bez filtrowania. htmlspecialchars() zamienia znaki specjalne na encje HTML. Od PHP 8.1 domyślnymi flagami są ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401; wcześniej apostrofy nie były zamieniane. Kto musi obsługiwać starsze wersje, podaje flagi wprost.

SQL injection zapobiegają przygotowane zapytania. Wartości są przekazywane oddzielnie od tekstu SQL i nie mogą zmienić zapytania:

<?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');

Szczegóły znajdują się w artykule Zapobieganie cross-site scriptingowi w PHP oraz na stronie o SQL injection.

Sprawdzanie danych wejściowych to drugi, oddzielny krok. filter_var() stwierdza, czy wartość ma prawidłowy format, na przykład adres e-mail lub liczbę całkowitą w dozwolonym zakresie. Nie zastępuje to jednak maskowania na wyjściu ani przygotowanego zapytania, ponieważ także formalnie prawidłowe wartości mogą zawierać znaki specjalne.

Trzymanie sekretów z dala od komunikatów o błędach

Niedocenianym wyciekiem danych są stacktrace. Gdy w funkcji wystąpi błąd, PHP zapisuje w logu łańcuch wywołań wraz z argumentami. Jeśli znajduje się tam hasło lub klucz API, trafia do logu. Od PHP 8.2 atrybut #[\SensitiveParameter] oznacza takie parametry; ich wartość pojawia się wtedy w trace tylko jako obiekt SensitiveParameterValue.

<?php
function anmelden(string $benutzer, #[\SensitiveParameter] string $passwort): bool
{
    // ... sprawdzenie ...
    throw new RuntimeException('Datenbank nicht erreichbar');
}

Według uwagi w podręczniku atrybut działa tylko w konkretnej implementacji, a nie w metodzie interfejsu. Proszę go więc ustawiać tam, gdzie kod faktycznie działa.

Sesje: bezpieczne ustawienia i nowe standardy

Sesje są częstym celem ataków. Trzy ustawienia są kluczowe: session.use_strict_mode=1 odrzuca identyfikatory sesji, których serwer sam nie wygenerował; session.cookie_httponly=1 uniemożliwia dostęp do ciasteczka sesji przez JavaScript; session.cookie_samesite=Lax utrudnia dołączanie go na obcych stronach. Według przyjętego RFC właśnie te trzy wartości staną się w PHP 8.6 domyślne. Proszę ustawić je samodzielnie do tego czasu, a także później wprost, aby konfiguracja nie zależała od ustawień domyślnych.

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

Więcej w artykule Zabezpieczanie sesji w PHP.

Czego wbudowane funkcje nie zapewniają

Projekt PHP jest w swojej polityce bezpieczeństwa wyraźny: PHP nie jest sandboxem. Obejścia open_basedir lub disable_functions, złośliwe dane przekazywane do unserialize() i niesprawdzone argumenty funkcji takich jak mysqli_query() nie są uznawane za luki bezpieczeństwa PHP. Dla operatorów oznacza to: te ustawienia są użytecznym utwardzaniem, ale nie granicą bezpieczeństwa, a unserialize() nie ma nic wspólnego z obcymi danymi.

Drugi punkt dotyczy PHP2Shell. CVE-2026-109618 i CVE-2026-109619 umożliwiają według php.net wykonanie kodu, zanim lub gdy działa Państwa aplikacja; w przypadku mod_php pokazano exploit, zanim w ogóle zostanie wykonany kod aplikacji. Żadna funkcja w Państwa kodzie nie może tego przechwycić. Bezpieczne programowanie i aktualna wersja PHP to dwa osobne obowiązki, a oba muszą być spełnione.

Jak konkretnie pomaga PHP SOS?

W audycie bezpieczeństwa aplikacji PHP sprawdzamy celowo:

  • Obsługa haseł i tokenów: Czy używane są password_hash() i random_bytes(), czy są rozwiązania własne?
  • Wyjście i zapytania: Gdzie dane wejściowe trafiają bez filtrowania do HTML, SQL lub poleceń powłoki?
  • Konfiguracja sesji: Czy Strict Mode, HttpOnly, SameSite i Secure są ustawione i nie da się ich nadpisać?
  • Środowisko uruchomieniowe: Czy działa wspierana wersja PHP z poprawkami z 21.10.2026?

Częste pytania

Jak prawidłowo przechowywać hasła w PHP?

Za pomocą password_hash() i PASSWORD_DEFAULT, a sprawdza się je przez password_verify(). Kolumna w bazie danych powinna według podręcznika mieścić do 255 znaków, ponieważ domyślny algorytm może się w przyszłości zmienić.

Czy rand() nadaje się do tokenów?

Nie. Do tokenów, kluczy i linków do resetu hasła należy używać random_bytes() lub random_int(). Według podręcznika dostarczają one kryptograficznie bezpiecznych wartości losowych.

Od kiedy Sodium jest częścią PHP?

Rozszerzenie Sodium do nowoczesnej kryptografii jest częścią PHP od wersji 7.2.0. Starsze wersje mogły je doinstalować tylko przez PECL.

Czy te funkcje chronią przed PHP2Shell?

Nie. Chronią przed błędami w Państwa aplikacji. PHP2Shell tkwi w samym interpreterze i jest zamykane wyłącznie aktualizacją PHP, po której następuje restart wszystkich procesów PHP.

Czy standardy sesji zmienią się w PHP 8.6?

Tak, według przyjętego RFC session.use_strict_mode i session.cookie_httponly zostaną domyślnie włączone, a session.cookie_samesite ustawione na Lax. Istniejące konfiguracje powinni Państwo mimo to ustawić sami, wprost.

Źródła

Kontakt natychmiast

Liczy się każda godzina. Proszę napisać do nas teraz.

Proszę krótko opisać system, wersję PHP i obserwacje. Skontaktujemy się z Państwem, ustalimy sytuację i będziemy pracować zdalnie, aż incydent zostanie zamknięty i udokumentowany.

Natychmiastowa pomoc