Stručně: Pomocí expose_php = Off v php.ini zmizí hlavička X-Powered-By: PHP/…. K tomu patří server_tokens off; v Nginx a ServerTokens Prod a ServerSignature Off v Apache. Žádný server tím bezpečnější není, automatizovaným skenům to ale bere hotový seznam verzí. Vlastní stav záplat poté ověřujte přes správce balíčků a procesy, ne přes hlavičky.
Vizitka v každé odpovědi
Kdo po 21. říjnu 2026 chtěl vědět, kolik serverů stále ukazuje starou verzi PHP, nemusel dlouho hledat. Mnoho webových serverů uvádí verzi PHP v každé jednotlivé odpovědi, například jako X-Powered-By: PHP/8.2.20. Celoplošné vyhledávací služby tyto údaje čtou a Unit 42 od Palo Alto Networks napočítala u PHP2Shell více než 22,6 milionu exponovaných, potenciálně zranitelných instancí.
Pro útočníky je takový údaj zkratkou. Mohou si cíle předtřídit, místo aby zkoušeli naslepo. Pro provozovatele je naopak bezcenný, protože nedokládá ani vlastní stav záplat: distribuce opravy často dodávají jako backport bez nového čísla verze.
Tento článek ukazuje, kde PHP a webový server prozrazují informace o verzi a jak je vypnout. Říká také otevřeně, co to přináší a co ne.
Kde se údaje o verzi všude objevují
Verze PHP je jen jedním z několika míst. Úplný pohled se vyplatí, protože jediné zapomenuté místo znehodnotí ostatní opatření.
| Místo nálezu | Příklad | Vypnout pomocí |
|---|---|---|
| Hlavička HTTP od PHP | X-Powered-By: PHP/8.3.x |
expose_php = Off v php.ini |
| Hlavička HTTP webového serveru | Server: nginx/1.x nebo Server: Apache/2.4.x (Debian) |
server_tokens off; popř. ServerTokens Prod |
| Chybové stránky webového serveru | řádek s verzí pod stránkami 404 nebo 500 | stejná nastavení, v Apache navíc ServerSignature Off |
| Hlavičky aplikace | vlastní údaje X-Powered-By frameworků |
fastcgi_hide_header popř. Header unset |
| Soubory ve webrootu | testovací soubory phpinfo(), soubory readme a changelog |
smazat nebo zablokovat |
| Chybová hlášení PHP | cesty a podrobnosti o verzi v prohlížeči | display_errors = Off |
Testovací soubory s phpinfo() jsou pro útočníky nejvýdatnějším zdrojem. Prozrazují nejen verzi, ale celou konfiguraci; více v článku Soubory phpinfo(): proč musí zmizet.
Vypnout expose_php v php.ini
Podle příručky PHP je expose_php standardně zapnuto a lze je měnit jen v php.ini, ne v poolu, ne přes .htaccess a ne za běhu. Hodnotu proto nastavte v php.ini každého provozního režimu, který obsluhuje weby, tedy například v Debianu a Ubuntu v /etc/php/<version>/fpm/ a případně v /etc/php/<version>/apache2/.
; php.ini webového SAPI, poté restartovat PHP-FPM popř. Apache
expose_php = Off
Pokud paralelně běží několik verzí PHP, potřebuje každá svůj zápis. Restart příslušné služby je povinný, protože PHP čte php.ini jen při startu.
Zkrátit hlavičky Server v Nginx a Apache
Nginx uvádí svou verzi standardně v hlavičce Server a na chybových stránkách. S server_tokens off; zůstane jen název produktu. Hlavičku X-Powered-By, kterou nastavuje sama aplikace, lze navíc odfiltrovat pomocí fastcgi_hide_header. Podle dokumentace Nginx skrývá Nginx sám od sebe jen Status a X-Accel-…, nikoli X-Powered-By.
# v bloku http, platí pro všechny weby
server_tokens off;
fastcgi_hide_header X-Powered-By;
V Apache řídí ServerTokens hlavičku Server a zároveň řádek s verzí pod chybovými stránkami. Nastavení podle dokumentace Apache platí jen pro celý server, ne pro jednotlivý VirtualHost. Protože odpovědi PHP-FPM přes mod_proxy_fcgi končí v jiné tabulce hlaviček než odpovědi samotného serveru, nastavte odstranění v obou variantách.
# konfigurace pro celý server, např. /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>
Konfiguraci před opětovným načtením zkontrolujte pomocí nginx -t popř. apachectl configtest. Jak pomocí hlaviček aktivně chránit návštěvníky, například pomocí HSTS nebo Content-Security-Policy, popisuje průvodce Bezpečnostní hlavičky pro weby.
Jak výsledek ověřit zvenčí
Po přechodu zkontrolujte každou doménu zvlášť, pokud možno i chybovou stránku. Následující příkazy posílají jen běžné požadavky na vaše vlastní weby:
# Hlavičky úvodní stránky
curl -sI https://www.example.de/ | grep -iE '^(server|x-powered-by):'
# Hlavičky neexistující stránky
curl -sI https://www.example.de/gibt-es-nicht-4711 | grep -iE '^(server|x-powered-by):'
Očekává se hlavička Server bez čísla verze a žádná X-Powered-By. Pokud tam stále stojí verze PHP, je zpravidla aktivní jiné php.ini nebo služba ještě nebyla restartována. Pokud před serverem stojí CDN, zkontrolujte navíc přímo origin server, pokud je dostupný.
Verzi PHP si přesto interně zaznamenejte: ve vašem soupisu serverů, se stavem balíčků a datem poslední kontroly. Stav záplat dokládejte přes server, jak je popsáno v článku Správná kontrola verze PHP a stavu záplat.
Co skrytí přináší a co ne
Upřímně řečeno je vypnutí údajů o verzi malé opatření s nízkou pracností. Snižuje pravděpodobnost, že se objevíte v cílených hledáních určitých verzí, a zmenšuje informace, které útočník získá bez námahy.
Nechrání však před automatizovanými útoky, které své požadavky prostě posílají na každý dostupný server. Jak takové hromadné skeny probíhají, popisuje článek Hromadné skeny po nezáplatovaném PHP. Proti PHP2Shell pomáhá jen aktualizace na PHP 8.5.12, 8.4.27, 8.3.36 nebo 8.2.35, popř. potvrzený backport, následovaná restartem všech procesů PHP.
Vedlejší účinek je naopak velmi užitečný: kdo navenek vypne údaje o verzích, musí si je interně pořádně evidovat. V situaci jako PHP2Shell právě tento přehled rozhoduje o tom, jak rychle zjistíte, které servery jsou dotčeny.
Skrytí proto dává smysl jako součást základního zpevnění, ne jako jednotlivé opatření. Patří do stejného kontrolního seznamu jako vypnuté chybové výstupy, smazané testovací soubory a uzamčené konfigurační hodnoty.
Jak konkrétně pomáhá PHP SOS?
- Zmapovat místa nálezu: Zkontrolujeme hlavičky, chybové stránky a webroot všech domén na údaje o verzi a zapomenuté testovací soubory.
- Upravit konfiguraci: Nastavíme
expose_php, hlavičky Server a filtry hlaviček v každé verzi PHP a každém webovém serveru a kontrolovaně restartujeme služby. - Stav záplat doložit interně: Verze a stavy balíčků zdokumentujeme tam, kam patří, tedy v soupisu, ne v hlavičce HTTP.
- Zasadit do zpevnění: Opatření je součástí našeho zpevnění serverů s PHP.
Časté dotazy
Udělá expose_php = Off můj server bezpečným?
Ne. Nastavení odstraní jen údaj o verzi z hlavičky HTTP. Zranitelná verze PHP zůstává zranitelná a automatizované útoky své požadavky často stejně zkoušejí na každém dostupném serveru. Útočníkům ale bere jednoduchý předvýběr a snižuje viditelnost ve vyhledávačích serverů.
Mohu expose_php nastavit v poolu FPM nebo pomocí .htaccess?
Podle příručky PHP lze expose_php měnit jen v php.ini. Hodnotu proto nastavte v php.ini každého webového SAPI a poté restartujte PHP-FPM nebo Apache.
Proč vidím X-Powered-By i přes expose_php = Off?
Pak hlavičku zpravidla nastavuje sama aplikace nebo framework, nebo je aktivní jiné php.ini. Hlavičku odstraňte navíc ve webovém serveru: pomocí fastcgi_hide_header v Nginx nebo Header unset v Apache.
Jak zkontroluji stav záplat, když verze už není vidět?
Přímo na serveru: správce balíčků, changelog balíčku s čísly CVE a čas spuštění procesů PHP. Údaj v hlavičce HTTP stejně nebyl důkazem, protože distribuce backporty často nasazují bez nového čísla verze.