Stručne: S expose_php = Off v php.ini zmizne hlavička X-Powered-By: PHP/…. K tomu patria server_tokens off; v Nginx a ServerTokens Prod a ServerSignature Off v Apache. Žiadny server to nerobí bezpečnejším, automatizovaným skenom to však berie hotový zoznam verzií. Vlastný stav záplat potom overujete cez správcu balíkov a procesy, nie cez hlavičky.
Vizitka v každej odpovedi
Kto po 21. októbri 2026 chcel vedieť, koľko serverov ešte ukazuje starú verziu PHP, nemusel dlho hľadať. Mnohé webové servery uvádzajú svoju verziu PHP v každej jednotlivej odpovedi, napríklad ako X-Powered-By: PHP/8.2.20. Celosvetové vyhľadávacie služby tieto údaje čítajú a Unit 42 od Palo Alto Networks napočítal pri PHP2Shell viac než 22,6 milióna exponovaných, potenciálne zraniteľných inštancií.
Pre útočníkov je taký údaj skratkou. Môžu ciele predtriediť, namiesto aby skúšali naslepo. Pre prevádzkovateľov je naopak zbytočný, pretože nedokazuje ani ich vlastný stav záplat: distribúcie často dodávajú opravy ako backport bez nového čísla verzie.
Tento príspevok ukazuje, kde PHP a webový server prezrádzajú informácie o verzii a ako údaje vypnúť. Otvorene hovorí aj o tom, čo to prináša a čo nie.
Kde všade sa údaje o verzii objavujú
Verzia PHP je len jedným z viacerých miest. Oplatí sa pozrieť na všetky, pretože jediné zabudnuté miesto znehodnotí ostatné opatrenia.
| Miesto nálezu | Príklad | Vypnúť cez |
|---|---|---|
| Hlavička HTTP od PHP | X-Powered-By: PHP/8.3.x |
expose_php = Off v php.ini |
| Hlavička HTTP webového servera | Server: nginx/1.x alebo Server: Apache/2.4.x (Debian) |
server_tokens off; resp. ServerTokens Prod |
| Chybové stránky webového servera | riadok s verziou pod stránkami 404 alebo 500 | rovnaké nastavenia, v Apache navyše ServerSignature Off |
| Hlavičky aplikácie | vlastné údaje X-Powered-By od frameworkov |
fastcgi_hide_header resp. Header unset |
| Súbory vo webovom koreni | testovacie súbory phpinfo(), súbory readme a changelog |
zmazať alebo zablokovať |
| Chybové hlásenia PHP | cesty a podrobnosti o verzii v prehliadači | display_errors = Off |
Testovacie súbory s phpinfo() sú pre útočníkov najvýdatnejším zdrojom. Prezrádzajú nielen verziu, ale celú konfiguráciu; viac v príspevku Súbory phpinfo(): prečo musia zmiznúť.
Vypnutie expose_php v php.ini
Podľa príručky PHP je expose_php štandardne zapnutý a dá sa meniť len v php.ini, nie v poole, nie cez .htaccess a nie za behu. Hodnotu preto nastavte v php.ini každého spôsobu prevádzky, ktorý doručuje weby, teda pri Debian a Ubuntu napríklad pod /etc/php/<version>/fpm/ a prípadne /etc/php/<version>/apache2/.
; php.ini webového SAPI, potom reštartovať PHP-FPM resp. Apache
expose_php = Off
Ak paralelne beží viacero verzií PHP, každá potrebuje svoj zápis. Reštart príslušnej služby je povinný, pretože PHP číta php.ini len pri štarte.
Skrátenie hlavičiek Server v Nginx a Apache
Nginx štandardne uvádza svoju verziu v hlavičke Server a na chybových stránkach. S server_tokens off; zostane len názov produktu. Hlavičku X-Powered-By, ktorú nastavuje samotná aplikácia, sa dá navyše odfiltrovať pomocou fastcgi_hide_header. Podľa dokumentácie Nginx sám Nginx skrýva len Status a X-Accel-…, nie X-Powered-By.
# v bloku http, platí pre všetky weby
server_tokens off;
fastcgi_hide_header X-Powered-By;
V Apache riadi ServerTokens hlavičku Server a zároveň riadok s verziou pod chybovými stránkami. Nastavenie podľa dokumentácie Apache platí len na úrovni celého servera, nie pre každý VirtualHost. Keďže odpovede PHP-FPM cez mod_proxy_fcgi pristanú v inej tabuľke hlavičiek než odpovede samotného servera, nastavte odstránenie v oboch variantoch.
# konfigurácia na úrovni celého servera, napr. /etc/apache2/conf-available/security.conf
ServerTokens Prod
ServerSignature Off
# vyžaduje mod_headers
<IfModule mod_headers.c>
Header unset X-Powered-By
Header always unset X-Powered-By
</IfModule>
Konfiguráciu pred opätovným načítaním skontrolujte pomocou nginx -t resp. apachectl configtest. Ako cez hlavičky aktívne zapnúť ochranu pre návštevníkov, napríklad pomocou HSTS alebo Content-Security-Policy, opisuje sprievodca Bezpečnostné hlavičky pre webové stránky.
Ako výsledok overiť zvonka
Po prechode skontrolujte každú doménu osobitne, podľa možnosti aj chybovú stránku. Nasledujúce príkazy posielajú len bežné požiadavky na vaše vlastné weby:
# Hlavičky úvodnej stránky
curl -sI https://www.example.de/ | grep -iE '^(server|x-powered-by):'
# Hlavičky neexistujúcej stránky
curl -sI https://www.example.de/gibt-es-nicht-4711 | grep -iE '^(server|x-powered-by):'
Očakáva sa hlavička Server bez čísla verzie a žiadne X-Powered-By. Ak tam stále stojí verzia PHP, je spravidla aktívna iná php.ini alebo služba ešte nebola reštartovaná. Ak pred serverom stojí CDN, skontrolujte navyše priamo pôvodný server, pokiaľ je dostupný.
Verziu PHP si aj tak interne evidujte: vo vašom inventári serverov, so stavom balíkov a dátumom poslednej kontroly. Stav záplat dokladujte cez server, ako je opísané v článku Správna kontrola verzie PHP a stavu záplat.
Čo skrývanie prináša a čo nie
Čestne zaradené je vypnutie údajov o verzii malým opatrením s nízkou náročnosťou. Znižuje pravdepodobnosť, že sa objavíte v cielených hľadaniach určitých verzií, a zmenšuje informácie, ktoré útočník získa bez námahy.
Nechráni však pred automatizovanými útokmi, ktoré svoje požiadavky jednoducho posielajú na každý dostupný server. Ako takéto hromadné skeny prebiehajú, opisuje príspevok Hromadné skeny po nezáplatovanom PHP. Proti PHP2Shell pomáha len aktualizácia na PHP 8.5.12, 8.4.27, 8.3.36 alebo 8.2.35, resp. potvrdený backport, nasledovaná reštartom všetkých procesov PHP.
Vedľajší účinok je naopak mimoriadne užitočný: kto vypne údaje o verziách smerom von, musí si verzie interne poriadne evidovať. V situácii ako PHP2Shell rozhoduje práve tento prehľad o tom, ako rýchlo zistíte, ktoré servery sú dotknuté.
Zmysluplné je preto skrývanie ako súčasť základného sprísnenia, nie ako samostatné opatrenie. Patrí do rovnakého kontrolného zoznamu ako vypnuté chybové výstupy, zmazané testovacie súbory a zablokované konfiguračné hodnoty.
Ako konkrétne pomáha PHP SOS?
- Zachytiť miesta nálezu: preveríme hlavičky, chybové stránky a webový koreň všetkých domén na údaje o verzii a zabudnuté testovacie súbory.
- Upraviť konfiguráciu: nastavíme
expose_php, hlavičky Server a filtre hlavičiek v každej verzii PHP a každom webovom serveri a riadene reštartujeme služby. - Stav záplat doložiť interne: verzie a stavy balíkov dokumentujeme tam, kam patria, v inventári namiesto v hlavičke HTTP.
- Zaradiť do sprísnenia: opatrenie je súčasťou nášho sprísnenia serverov PHP.
Časté otázky
Robí expose_php = Off môj server bezpečným?
Nie. Nastavenie odstráni len údaj o verzii z hlavičky HTTP. Zraniteľná verzia PHP zostáva zraniteľná a automatizované útoky svoje požiadavky často skúšajú na každom dostupnom serveri tak či tak. Útočníkom však berie jednoduchý predvýber a znižuje viditeľnosť vo vyhľadávačoch pre servery.
Môžem expose_php nastaviť v poole FPM alebo cez .htaccess?
Podľa príručky PHP sa expose_php dá meniť len v php.ini. Hodnotu preto nastavte v php.ini každého webového SAPI a potom reštartujte PHP-FPM alebo Apache.
Prečo vidím X-Powered-By napriek expose_php = Off?
Potom hlavičku spravidla nastavuje samotná aplikácia alebo framework, alebo je aktívna iná php.ini. Hlavičku navyše odstráňte vo webovom serveri: pomocou fastcgi_hide_header v Nginx alebo Header unset v Apache.
Ako zistím stav záplat, keď verzia už nie je viditeľná?
Cez samotný server: správca balíkov, changelog balíka s číslami CVE a čas spustenia procesov PHP. Údaj v hlavičke HTTP aj tak nebol dôkazom, pretože distribúcie často nasadzujú backporty bez nového čísla verzie.