Röviden: Az Nginx PHP-hez való biztonságos konfigurálásához csak olyan szkripteket adjon át a PHP-FPM-nek, amelyek valóban léteznek, front controlleres alkalmazásoknál kizárólag az index.php-t. Ehhez jönnek a zárolt dotfájlok, mint a .git és a .env, egy alapértelmezett szerver az ismeretlen hosztnevekhez, megfelelő méretkorlátok és a security.limit_extensions = .php a poolban. Ez nem véd a magában a PHP-ban lévő rések ellen, de korlátozza, mi futtatható egy hiba után.
A legveszélyesebb sorok a PHP-locationben állnak
A PHP2Shell óta sok csapat ellenőrzi a PHP-FPM-verzióit és poolait, ahogyan azt az Az Nginx biztonságossá tétele PHP-FPM-mel oldal leírja, és a frissítés után újraindítja az összes workert. Egy második pillantás magára az Nginx-konfigurációra vonatkozik. Ott dől el, mely fájlokat hajtják végre egyáltalán PHP-ként.
Sok konfigurációban van egy blokk, amely minden .php végű kérést átad a PHP-FPM-nek, akárhol is van a fájl. Ha egy bejuttatott PHP-fájl egy feltöltési mappába kerül, a szerver végrehajtja. Egy fájlhibából így hátsó ajtó lesz.
Ez a cikk az Nginx oldalára koncentrál: mely direktívák számítanak, hogyan hat a location-blokkok sorrendje, és hogyan tesztelje az eredményt.
Hogyan dönt az Nginx, melyik blokk érvényesül
Aki az Nginxet biztonságosan akarja konfigurálni PHP-hez, annak ismernie kell a location-blokkok kiválasztását. Az Nginx dokumentációja szerint így zajlik:
- A
location =pontos találata azonnal véget vet a keresésnek. - A prefix-locationök közül a leghosszabb illeszkedőt jegyzi meg. Ha
^~van rajta, reguláris kifejezéseket már nem vizsgál. - Egyébként a reguláris kifejezéseket (
~,~*) a konfigurációs fájl sorrendjében vizsgálja; az első találat nyer. - Ha egy reguláris kifejezés sem illik, a megjegyzett prefix-location érvényes.
Ebből két gyakorlati szabály következik. A feltöltési mappákban a PHP zárolását vagy ^~ prefixként kell létrehozni, vagy reguláris kifejezésként az általános PHP-blokk elé kell tenni. És egy normál prefix-location, mint a location /uploads/, nem véd, mert a .php-re vonatkozó reguláris kifejezés túlszárnyalja.
Egy biztonságos alapkonfiguráció
A következő példa egy front controlleres alkalmazás szerverblokkját mutatja, ahogyan a Laravelnél, a Symfonynál, a Shopware 6-nál vagy sok egyedi fejlesztésnél szokásos. Az útvonalakat, a sockete és a tanúsítványokat igazítsa.
server {
listen 443 ssl;
server_name www.example.de;
root /var/www/seite1/public;
index index.php;
ssl_certificate /etc/ssl/seite1/fullchain.pem;
ssl_certificate_key /etc/ssl/seite1/privkey.pem;
server_tokens off;
client_max_body_size 32m;
# A Let's Encrypt és más ismert útvonalak engedélyezése
location ^~ /.well-known/ {
try_files $uri =404;
}
# Rejtett fájlok és mappák zárolása (.git, .env, .htaccess)
location ~ /\. {
deny all;
}
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# Csak a front controllert adják át a PHP-FPM-nek
location = /index.php {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_hide_header X-Powered-By;
fastcgi_pass unix:/run/php/seite1.sock;
}
# Minden más PHP-fájlt nem hajtanak végre
location ~ \.php$ {
return 404;
}
}
A $realpath_root feloldja a szimbolikus hivatkozásokat. Ez fontos az olyan telepítéseknél, amelyekben egy váltakozó szimbolikus link mutat az aktuális kiadásra, hogy a PHP-FPM és az OPcache a helyes útvonalat lássa. Vegye figyelembe továbbá: az Nginx dokumentációja szerint a fastcgi_param direktívákat csak akkor örökli a magasabb szintekről, ha az aktuális szinten nincsenek sajátok. Ezért az include fastcgi_params; ugyanabba a blokkba tartozik.
A klasszikus CMS-eknek, mint a WordPress, a TYPO3 vagy a Contao, több belépési pontjuk van. Náluk a front controller blokkot egy általános PHP-locationre cserélje, amely csak létező fájlokat ad át (try_files $uri =404;), és zárolja a végrehajtást az összes írható mappában. Hogyan sikerül ez, azt a PHP-végrehajtás tiltása a feltöltési mappákban cikk írja le.
A második védelem a PHP-FPM-ben
Az Nginx dönti el, mi kerül átadásra, a PHP-FPM dönti el, mit hajt végre. A PHP kézikönyve szerint a PHP-FPM alapértelmezetten a .php és .phar végű fájlokat hajtja végre, és maga javasolja, hogy ezt korlátozzák a .php-re. Ez felfogja a webszerver konfigurációs hibáit.
; a poolban, pl. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
listen = /run/php/seite1.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
A socketnek csak az Nginx számára szabad elérhetőnek lennie. Az FPM-portokat a hálózaton, például a 9000-et, nem szabad kifelé megnyitni. Hogyan mutat a szerver egészében csak a szükséges portokat, azt a Tűzfal webszerverekhez: csak a szükséges portokat nyissa meg írja le.
Ismeretlen hosztnevek és további beállítócsavarok
Saját alapértelmezett szerver nélkül az Nginx az ismeretlen hosztnevekre irányuló kéréseket az első illeszkedő szerverblokkal válaszolja meg. Az automatizált vizsgálatok, amelyek csak az IP-címet szólítják meg, ilyenkor közvetlenül az Ön alkalmazásába kerülnek. Egy saját alapértelmezett szerver válasz nélkül lezárja az ilyen kéréseket.
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
ssl_reject_handshake on;
return 444;
}
További, bevált pontok:
| Beállítócsavar | Ajánlás | Cél |
|---|---|---|
server_tokens |
off |
nincs verziószám a fejlécben és a hibaoldalakon |
client_max_body_size |
a post_max_size-hoz illő |
a nagy kéréseket korán elutasítani |
autoindex |
ki (alapértelmezés) | nincsenek könyvtárlisták |
fastcgi_hide_header |
X-Powered-By |
nincs PHP-verzió kifelé |
| Státuszoldalak | pm.status_path csak belsőleg |
nincsenek nyilvános üzemi adatok |
| Mentési fájlok | .sql, .zip, .bak a webrootban zárolni vagy eltávolítani |
adatbázisok letöltése nélkül |
A verziómegjelölésekről bővebben az expose_php és Server-fejléc cikkben.
Egy további beállítócsavar az engedélyezett HTTP-metódusokat érinti. A legtöbb weboldalnak csak GET, HEAD és POST kell. A limit_except-tel más metódusok elutasíthatók egy locationben; az Nginx dokumentációja szerint a GET engedélyezése automatikusan a HEAD-et is engedélyezi. Előtte ellenőrizze, hogy az alkalmazás felületei használnak-e például PUT-ot vagy DELETE-et, mert a REST API-k gyakran igen.
Tesztelés az újratöltés előtt
Minden módosítást először az nginx -t paranccsal ellenőrizzen, és csak utána töltse újra az Nginxet. Ezután tesztelje a viselkedést kívülről normál kérésekkel a saját domainjére:
sudo nginx -t && sudo systemctl reload nginx
# Elvárt: 403 vagy 404
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.git/HEAD
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env
# Elvárt: 404, mert csak a front controllert hajtják végre
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/info.php
# Mely blokkok adnak át a PHP-FPM-nek?
sudo nginx -T 2>/dev/null | grep -nE "location|fastcgi_pass"
Minden nagyobb módosítás előtt mentse az nginx -T teljes kimenetét dátummal. Ez tartalmazza az egész érvényes konfigurációt az összes beágyazott fájllal együtt. Ha egy módosítás után valami félresikerül, az összevetés azonnal megmutatja, mi különbözik. A következő kritikus résnél ezzel emellett megbízható alapja van az állapotfelméréshez, anélkül hogy először fájlokat kellene összegyűjtenie.
A konfigurációt előbb egy tesztkörnyezetben vagy a szerverblokk egy másolatán módosítsa. Egy elfelejtett belépési pont, például egy fizetési callback, különben csak akkor tűnik fel, amikor elmaradnak a rendelések.
Hogyan segít konkrétan a PHP SOS?
- A konfiguráció olvasása: Az
nginx -Tsegítségével kiértékeljük a teljes Nginx-konfigurációt, és minden PHP-átadást hozzárendelünk a weboldalához és a poolhoz. - A belépési pontok meghatározása: A fejlesztőivel közösen meghatározzuk, mely szkripteket kell végrehajtani, és a többit zároljuk.
- Megvalósítás és tesztelés: Igazítjuk a szerverblokkokat és poolokat, az
nginx -tparanccsal ellenőrizzük, és teszteljük az űrlapokat, fizetési utakat és feltöltéseket. - Tartós védelem: A konfiguráció a szerverkeményítésünk és a szervere dokumentációjának részévé válik.
Gyakori kérdések
Újra kell indítani az Nginxet egy PHP-frissítés után?
A PHP-javításhoz nem, mert az Nginx nem tartalmaz PHP-t. Az összes PHP-FPM-szolgáltatást kell újraindítani. Ha közben az Nginx-konfigurációt is módosítja, előtte ellenőrizze az nginx -t paranccsal, majd töltse újra az Nginxet.
Miért csak az index.php-t adjam át a PHP-nak?
Sok modern alkalmazásnak egyetlen belépési pontja van, a front controller. Ha csak ezt a fájlt adják át a PHP-FPM-nek, egy máshol bejuttatott PHP-fájl nem futtatható a böngészőn keresztül. Sok belépési ponttal rendelkező rendszereknél ez a minta nem lehetséges.
Mit ad a security.limit_extensions a PHP-FPM-ben?
A beállítás meghatározza, mely fájlvégződéseket hajtja végre a PHP-FPM szkriptként. A PHP kézikönyve szerint az alapértelmezés a .php .phar; a .php-re való korlátozás ajánlott. Ez felfogja a webszerver-konfiguráció hibáit, de nem pótolja azt.
Az Nginx-szabályok védelmet jelentenek a PHP2Shell ellen?
Nem. A PHP2Shell a PHP-értelmezőben van, és csak a javított verzióra való frissítés és az összes worker újraindítása zárja le. Egy biztonságos Nginx-konfiguráció csökkenti a támadási felületet, és korlátozza a kárt egy behatolás után.