Krótko: Rozszerzenia PHP (extensions) to moduły w C, które uzupełniają PHP o funkcje, na przykład sterowniki baz danych (PDO), szyfrowanie (Sodium, OpenSSL) czy pamięć podręczną bajtkodu OPcache. Podręcznik PHP rozróżnia rozszerzenia Core, Bundled, External i PECL. Ładuje się je przez extension lub zend_extension w php.ini. Każde rozszerzenie działa w procesie PHP z jego uprawnieniami. Dlatego obowiązuje: ładować tylko to, co potrzebne, i aktualizować razem z PHP.
Czym są rozszerzenia PHP?
Rdzeń PHP, czyli Zend Engine, potrafi wykonywać kod, ale wiele z tego, czego potrzebują aplikacje, znajduje się w rozszerzeniach. Są napisane w C i albo wkompilowane na stałe w PHP, albo ładowane przy starcie jako biblioteka współdzielona (.so w systemie Linux, .dll w systemie Windows).
Ważne dla osób podejmujących decyzje: rozszerzenia nie są wtyczkami aplikacji, lecz częścią środowiska uruchomieniowego PHP. Instaluje je dostawca hostingu lub administrator serwera, a nie agencja w CMS. Jeśli rozszerzenia brakuje, aplikacja zwykle zgłasza błąd przy instalacji lub aktualizacji.
Równie ważne jest odróżnienie od pakietów Composera. Composer instaluje biblioteki napisane w PHP, które leżą w folderze projektu, na przykład pakiet do poczty lub PDF. Rozszerzenia to natomiast skompilowany kod ładowany przy starcie PHP, obowiązujący dla wszystkich aplikacji na serwerze. Wiele pakietów Composera zakłada określone rozszerzenia i odnotowuje to w swoim composer.json wpisami takimi jak ext-intl lub ext-sodium. Kto chce sprawdzić, czy projekt ma wszystkie potrzebne rozszerzenia, może w folderze projektu wykonać composer check-platform-reqs.
Jakie są rodzaje rozszerzeń?
Podręcznik PHP przypisuje rozszerzenia do czterech grup:
| Grupa | Znaczenie według podręcznika | Przykłady z podręcznika |
|---|---|---|
| Core | część rdzenia PHP, nie do wyłączenia | Arrays, Date/Time, Hash, JSON, PCRE, SPL, Strings |
| Bundled | dostarczane z PHP | BC Math, Ctype, Fileinfo, Filter, GD, intl, mbstring, PDO, Sessions |
| External | dostarczane z PHP, wymagają zewnętrznych bibliotek | cURL, DOM, GMP, LDAP, OpenSSL, Sodium, Zip |
| PECL | dostępne przez PECL, częściowo z zewnętrznymi bibliotekami | APCu, Memcached, MongoDB, Yaml |
Przyporządkowanie może się zmieniać. W PHP 8.4 według strony wydania rozszerzenia IMAP, OCI8, PDO_OCI i pspell usunięto z dystrybucji i przeniesiono do PECL. Kto ich używa, potrzebuje po aktualizacji osobnej instalacji, którą również trzeba utrzymywać.
Jak ładuje się rozszerzenia?
Rozszerzenia współdzielone są według podręcznika ładowane dyrektywą extension w php.ini; rozszerzenia Zend, które głębiej ingerują w silnik, przez zend_extension. Obie mogą znajdować się tylko w php.ini. Katalog określa extension_dir, dla którego podręcznik zaleca ścieżkę bezwzględną.
; zwykłe rozszerzenia
extension=pdo_mysql
extension=sodium
extension=intl
; rozszerzenie Zend: OPcache (ładować przed Xdebug, jeśli oba aktywne)
zend_extension=opcache
Dystrybucje takie jak Debian i Ubuntu zapisują dla każdego rozszerzenia osobny mały plik .ini w katalogu skanowania, na przykład w /etc/php/8.3/mods-available/, i aktywują go dla każdego SAPI przez phpenmod i phpdismod. Jak PHP wczytuje te pliki, wyjaśnia strona php.ini wyjaśniony.
Rozszerzenia instaluje się zwykle przez menedżera pakietów, na przykład jako pakiet php8.3-intl. Rozszerzenia PECL można zbudować za pomocą pecl lub phpize. Według podręcznika PECL jest wycofany; zaleca się PHP Installer for Extensions (PIE). Kto buduje PHP całkowicie samodzielnie, znajdzie wskazówki na stronie Kompilowanie PHP z kodu źródłowego.
Sprawdzanie rozszerzeń: które są naprawdę załadowane?
Poniższe polecenia są wyłącznie odczytowe. Proszę pamiętać, że wiersz poleceń może ładować inne rozszerzenia niż strona.
php -m # moduły CLI
php-fpm8.3 -m # moduły PHP-FPM 8.3 (nazwa zależna od dystrybucji)
php --re sodium | head -n 5 # funkcje rozszerzenia
php --ri opcache # konfiguracja rozszerzenia
php -r 'var_dump(extension_loaded("intl"));'
W kodzie aplikacje sprawdzają przez extension_loaded(), czy rozszerzenie jest dostępne, a przez get_loaded_extensions(), które są załadowane:
<?php
$benoetigt = ['pdo_mysql', 'mbstring', 'intl', 'sodium'];
$fehlend = array_diff($benoetigt, array_map('strtolower', get_loaded_extensions()));
echo $fehlend ? 'Fehlt: ' . implode(', ', $fehlend) : 'Alle Erweiterungen vorhanden';
Rozszerzenia i bezpieczeństwo: mniej znaczy lepiej
Rozszerzenia działają w tym samym procesie co PHP i z tymi samymi uprawnieniami. Błąd w rozszerzeniu może więc być równie poważny jak błąd w rdzeniu. Wynikają z tego cztery zasady:
- Ładować tylko to, co potrzebne. Każde dodatkowe rozszerzenie zwiększa powierzchnię ataku. Proszę sprawdzić swoją listę z wymaganiami systemowymi aplikacji.
- Aktualizować razem z PHP. Rozszerzenia dostarczane razem z PHP przychodzą z aktualizacją PHP. Rozszerzenia PECL i zewnętrzne wymagają własnych aktualizacji i muszą pasować do nowej wersji PHP.
- Narzędzia deweloperskie nie na produkcję. Debuggery i profilery, takie jak Xdebug, należą tylko do środowisk deweloperskich.
- Celowo blokować funkcje. Tam, gdzie rozszerzenia wnoszą funkcje do poleceń systemowych, pomaga artykuł Prawidłowe użycie disable_functions.
W PHP2Shell luki tkwią w rdzeniu PHP, a nie w rozszerzeniu. Wyłączenie modułów ich nie zamyka; potrzebna jest aktualizacja do 8.5.12, 8.4.27, 8.3.36 lub 8.2.35 z restartem wszystkich procesów PHP. Po aktualizacji należy sprawdzić, czy wszystkie rozszerzenia są znów ładowane, ponieważ brakujące moduły często wychodzą na jaw dopiero przy określonych funkcjach. Jak trwale panować nad zależnościami, opisuje artykuł Utrzymywanie zależności w aktualnym stanie.
Jak konkretnie pomaga PHP SOS?
- Inwentaryzacja: Zestawiamy dla każdego SAPI wszystkie załadowane rozszerzenia z pochodzeniem i wersją.
- Porządkowanie: Porównujemy listę z potrzebami Państwa aplikacji i po teście dezaktywujemy to, co zbędne.
- Aktualizacja: W ramach utwardzania serwera doprowadzamy PHP i wszystkie rozszerzenia zewnętrzne do utrzymywanego stanu.
- Kontrola po aktualizacjach: Sprawdzamy, że po każdej aktualizacji PHP wszystkie potrzebne moduły są znów załadowane.
Częste pytania
Jaka jest różnica między extension a zend_extension?
Przez extension PHP ładuje zwykłe rozszerzenia, takie jak sterowniki baz danych. Przez zend_extension ładowane są według podręcznika rozszerzenia Zend, które głębiej ingerują w silnik, na przykład OPcache lub Xdebug. Obie dyrektywy mogą znajdować się tylko w php.ini.
Jak zobaczyć, które rozszerzenia są załadowane?
W wierszu poleceń przez php -m, dla strony przez funkcję get_loaded_extensions() w krótko umieszczonym pliku kontrolnym albo przez php-fpm -m danej wersji. Proszę pamiętać, że CLI i webowe SAPI mogą ładować różne rozszerzenia.
Czym jest PECL, a czym PIE?
PECL to katalog rozszerzeń PHP udostępnianych przez system pakietów PEAR. Według podręcznika PHP PECL jest wycofany; zamiast niego zaleca się PHP Installer for Extensions (PIE).
Czy wyłączenie rozszerzenia zamyka PHP2Shell?
Nie. Luki PHP2Shell tkwią w rdzeniu PHP, a nie w rozszerzeniu, które można wyłączyć. Mniej rozszerzeń zmniejsza ogólnie powierzchnię ataku, ale nie zastępuje aktualizacji do poprawionej wersji.