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ć →

PHP i bazy danych: PDO i mysqli

PHP komunikuje się z bazami danych przez PDO lub mysqli. Oto różnice, bezpieczne zapytania z prepared statements i co zrobić z dostępami do bazy po incydencie na serwerze.

Stan 5 min czytaniaWiedza o PHP

Krótko: PHP korzysta z baz danych przez dwa rozpowszechnione interfejsy: PDO (PHP Data Objects) pracuje z wieloma systemami baz danych przez jednolity interfejs, mysqli jest dopasowane do MySQL i MariaDB. W obu przypadkach prepared statements, czyli zapytania z symbolami zastępczymi, niezawodnie chronią przed SQL injection. Od PHP 8.0 (PDO) i odpowiednio 8.1 (mysqli) oba domyślnie zgłaszają błędy jako wyjątki.

Jak PHP komunikuje się z bazami danych

Prawie każda aplikacja PHP zapisuje swoje treści w bazie danych: strony, zamówienia, konta użytkowników, ustawienia. Skrypt PHP nawiązuje w tym celu połączenie, wysyła zapytanie w języku SQL i przetwarza wynik. Dane dostępowe znajdują się zwykle w pliku konfiguracyjnym na tym samym serwerze.

Dla zarządu jest to ważne, ponieważ baza danych zawiera zwykle najcenniejsze dane firmy. Kto może wykonać kod na serwerze WWW, może z reguły także odczytać plik konfiguracyjny i tymi danymi dostępowymi uzyskać dostęp do bazy danych.

PDO i mysqli w porównaniu

Cecha PDO mysqli
Bazy danych wiele, przez sterowniki takie jak PDO_MYSQL, PDO_PGSQL, PDO_SQLITE, PDO_SQLSRV, PDO_OCI MySQL i MariaDB
Symbole zastępcze nazwane (:name) i pozycyjne (?) pozycyjne (?)
Styl obiektowy obiektowy i proceduralny
Błędy jako wyjątki domyślnie od PHP 8.0.0 domyślnie od PHP 8.1.0
Skrócona forma zapytań z parametrami prepare() i execute() z tablicą execute_query() od PHP 8.2.0

W praktyce często decyduje framework lub CMS. Wiele z nich ma własną warstwę bazodanową, która wewnętrznie używa PDO lub mysqli. Kto przejmuje aplikację, może prostym wyszukiwaniem w kodzie źródłowym ustalić, jakiego interfejsu używa się i gdzie powstają zapytania:

# Gdzie aplikacja nawiązuje połączenia, gdzie powstają zapytania?
grep -rn --include='*.php' -E 'new PDO|new mysqli|mysqli_connect|->query\(' /var/www/app/src | head -50

Miejsca z ->query( nie są automatycznie niebezpieczne. Zasługują jednak na drugie spojrzenie, ponieważ wartości mogą tam trafić bezpośrednio do tekstu SQL zamiast być przekazane przez symbole zastępcze. Zwłaszcza starsze projekty mieszają oba style, a kontrola opłaca się przed każdą większą aktualizacją.

Prepared statements: najważniejszy wzorzec

W prepared statement zapytanie z symbolami zastępczymi jest wysyłane do bazy danych, a wartości są przekazywane osobno. Według podręcznika PHP chroni to przed SQL injection, jeśli wszystkie dane od użytkownika przechodzą przez symbole zastępcze.

<?php
declare(strict_types=1);

$pdo = new PDO(
    'mysql:host=localhost;dbname=shop;charset=utf8mb4',
    $dbUser,
    $dbPass,
    [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);

$stmt = $pdo->prepare('SELECT id, name FROM kunden WHERE plz = :plz AND aktiv = :aktiv');
$stmt->execute(['plz' => $plz, 'aktiv' => 1]);

foreach ($stmt as $zeile) {
    echo htmlspecialchars($zeile['name'], ENT_QUOTES, 'UTF-8'), "\n";
}

To samo z mysqli w skróconej formie, która istnieje od PHP 8.2:

<?php
$db = new mysqli('localhost', $dbUser, $dbPass, 'shop');
$ergebnis = $db->execute_query('SELECT id, name FROM kunden WHERE plz = ?', [$plz]);

foreach ($ergebnis as $zeile) {
    echo htmlspecialchars($zeile['name'], ENT_QUOTES, 'UTF-8'), "\n";
}

Programiści powinni znać dwie granice. Symbole zastępcze nie mogą stać w cudzysłowach; przy wyszukiwaniach LIKE znaki wieloznaczne % należą do przekazywanej wartości. I symbole zastępcze zastępują tylko wartości, a nie nazwy tabel czy kolumn. Jak bezpiecznie rozwiązywać takie przypadki szczególne, pokazuje poradnik Zapobieganie SQL injection w PHP.

Obsługa błędów: wyjątki zamiast cichych błędów

Dawniej oba interfejsy domyślnie pracowały cicho: nieudane zapytanie zwracało false, a kto tego nie sprawdził, pracował dalej z pustymi danymi. To się zmieniło:

  • PDO: Od PHP 8.0.0 PDO::ERRMODE_EXCEPTION jest ustawieniem domyślnym. Błędy zgłaszają PDOException.
  • mysqli: Od PHP 8.1.0 raportowanie błędów jest ustawione na MYSQLI_REPORT_ERROR i MYSQLI_REPORT_STRICT. Błędy zgłaszają mysqli_sql_exception; wcześniej raportowanie było wyłączone.

Dla bezpieczeństwa oznacza to: wyjątki trzeba przechwytywać i zapisywać w dzienniku, ale nigdy nie mogą trafić do przeglądarki z tekstem SQL, nazwami tabel lub danymi dostępowymi. Jak to czysto rozdzielić, opisuje strona Błędy i wyjątki w PHP.

Prawidłowe nadawanie danych dostępowych i uprawnień

Baza danych jest chroniona tak dobrze, jak jej dane dostępowe. Sprawdziły się te zasady:

  1. Osobny użytkownik dla każdej aplikacji: Nigdy nie używać administratora bazy danych dla strony.
  2. Tylko potrzebne uprawnienia: Strona potrzebuje zwykle odczytu, zapisu, zmiany i usuwania we własnej bazie, ale nie uprawnień do innych baz ani funkcji serwera.
  3. Bez połączenia zdalnego bez powodu: Baza danych powinna być osiągalna tylko z serwera WWW, a nie z internetu.
  4. Dane dostępowe poza katalogiem głównym WWW: Pliki konfiguracyjne i .env nie mogą być dostępne przez URL. Więcej w artykule Ochrona danych dostępowych i plików .env.
  5. Szyfrowane połączenie przy rozdzielonych serwerach: Jeśli baza danych leży na innym komputerze, połączenie powinno być szyfrowane, aby dane dostępowe i treści nie szły przez sieć jawnym tekstem.
  6. Własne dostępy do konserwacji: Kopie zapasowe, analizy i administratorzy dostają własnych użytkowników. Dzięki temu w dzienniku można prześledzić, kto co zrobił, a dostęp można zablokować, nie zakłócając działania strony.

Bazy danych, PHP2Shell i przypadek poważny

PHP2Shell nie dotyczy samej bazy danych, lecz interpretera PHP: CVE-2026-109618 i CVE-2026-109619 umożliwiają wykonanie złośliwego kodu bez logowania. Jeśli się to uda, kod działa z uprawnieniami procesu PHP i może zazwyczaj odczytać plik konfiguracyjny z danymi dostępowymi do bazy. Prepared statements tu nie pomagają, ponieważ atak w ogóle nie przechodzi przez zapytanie SQL.

Obowiązkowa jest więc aktualizacja do PHP 8.5.12, 8.4.27, 8.3.36 lub 8.2.35 i restart wszystkich procesów PHP. Jeśli są wskazówki na udany atak, należą do tego nowe dane dostępowe do bazy, sprawdzenie bazy pod kątem wstrzykniętych treści i ocena obowiązku zgłoszenia na podstawie RODO. Sensowne jest tu uporządkowane reagowanie na incydenty (Incident Response).

Wskazówka

Hasła do bazy danych proszę zmieniać dopiero po oczyszczeniu serwera. Dopóki działa złośliwy kod, może on odczytać także nowe dane dostępowe.

Jak konkretnie pomaga PHP SOS?

  • Sprawdzamy, jak Państwa aplikacja korzysta z bazy danych oraz czy użytkownicy, uprawnienia i dostęp sieciowy odpowiadają minimum.
  • Kontrolujemy, czy pliki konfiguracyjne i z danymi dostępowymi leżą poza katalogiem głównym WWW i nie są publicznie dostępne.
  • Po incydencie odnawiamy dane dostępowe we właściwej kolejności i sprawdzamy bazę danych pod kątem wstrzykniętego kodu.
  • Dokumentujemy wyniki tak, aby mogli je prześledzić inspektorzy ochrony danych i ubezpieczyciele.

Częste pytania

Czy używać PDO, czy mysqli?

W nowych projektach PDO jest zwykle bardziej elastycznym wyborem, ponieważ pracuje z wieloma bazami danych przez ten sam interfejs. mysqli ma sens, jeśli używają Państwo wyłącznie MySQL lub MariaDB i potrzebują ich funkcji specjalnych. Oba są bezpieczne, jeśli konsekwentnie stosuje się prepared statements.

Czy PDO przy błędach automatycznie zgłasza wyjątki?

Tak, od PHP 8.0.0 PDO::ERRMODE_EXCEPTION jest ustawieniem domyślnym. Wcześniej był to tryb cichy, w którym błędy dało się odczytać tylko przez errorCode() i errorInfo(). Starsze aplikacje często nadal ustawiają ten tryb wprost.

Czy symbole zastępcze mogą zastępować także nazwy tabel lub kolumn?

Nie. Symbole zastępcze oznaczają tylko wartości. Nazwy tabel i kolumn, na przykład do sortowania, trzeba sprawdzić względem stałej listy dozwolonych nazw, zanim zostaną wstawione do zapytania.

Czy po PHP2Shell muszę zmienić hasło do bazy danych?

Sama aktualizacja tego nie wymaga. Jeśli jednak są wskazówki, że serwer był skompromitowany, wszystkie dane dostępowe w plikach konfiguracyjnych należy uznać za znane. Wtedy powinni je Państwo odnowić po oczyszczeniu.

Ź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