Na kratko: Z expose_php = Off v php.ini glava X-Powered-By: PHP/… izgine. K temu sodijo server_tokens off; v Nginx ter ServerTokens Prod in ServerSignature Off v Apache. To ne naredi nobenega strežnika varnejšega, vendar samodejnim skeniranjem vzame pripravljen seznam različic. Lastno stanje popravkov nato preverjate prek upravljalnika paketov in procesov, ne prek glav.
Vizitka v vsakem odgovoru
Kdor je po 21. oktobru 2026 želel vedeti, koliko strežnikov še kaže staro različico PHP, ni dolgo iskal. Številni spletni strežniki različico PHP navajajo v vsakem posameznem odgovoru, na primer kot X-Powered-By: PHP/8.2.20. Spletne iskalne storitve te navedbe sproti berejo, Unit 42 podjetja Palo Alto Networks pa je za PHP2Shell naštel več kot 22,6 milijona izpostavljenih, potencialno ranljivih instanc.
Za napadalce je taka navedba bližnjica. Cilje lahko vnaprej razvrstijo, namesto da bi poskušali na slepo. Za upravljavce je po drugi strani neuporabna, saj ne dokazuje niti lastnega stanja popravkov: distribucije popravke pogosto dostavljajo kot backport brez nove številke različice.
Ta prispevek pokaže, kje PHP in spletni strežnik izdajata podatke o različicah in kako navedbe izklopite. Odkrito pove tudi, kaj to prinese in kaj ne.
Kje se podatki o različicah vse pojavljajo
Različica PHP je samo eno od več mest. Poln pogled se splača, ker ena sama pozabljena točka razvredoti druge ukrepe.
| Mesto najdbe | Primer | Izklop prek |
|---|---|---|
| Glava HTTP iz PHP | X-Powered-By: PHP/8.3.x |
expose_php = Off v php.ini |
| Glava HTTP spletnega strežnika | Server: nginx/1.x ali Server: Apache/2.4.x (Debian) |
server_tokens off; oz. ServerTokens Prod |
| Strani z napakami spletnega strežnika | vrstica z različico pod stranmi 404 ali 500 | iste nastavitve, v Apache dodatno ServerSignature Off |
| Glava aplikacije | lastne navedbe X-Powered-By ogrodij |
fastcgi_hide_header oz. Header unset |
| Datoteke v spletnem korenu | testne datoteke phpinfo(), datoteke readme in changelog |
izbrišite ali zaprite |
| Sporočila o napakah PHP | poti in podrobnosti o različici v brskalniku | display_errors = Off |
Testne datoteke s phpinfo() so za napadalce najizdatnejši vir. Razkrijejo ne samo različice, ampak celotno konfiguracijo; več o tem v prispevku Datoteke phpinfo(): zakaj morajo izginiti.
Izklop expose_php v php.ini
Po priročniku PHP je expose_php privzeto vklopljen in ga je mogoče spremeniti samo v php.ini, ne v poolu, ne prek .htaccess in ne med izvajanjem. Vrednost zato nastavite v php.ini vsakega načina delovanja, ki dostavlja spletne strani, pri Debianu in Ubuntuju torej na primer pod /etc/php/<version>/fpm/ in po potrebi /etc/php/<version>/apache2/.
; php.ini spletnega SAPI, nato znova zaženite PHP-FPM oz. Apache
expose_php = Off
Če vzporedno teče več različic PHP, vsaka potrebuje svoj vnos. Ponovni zagon zadevne storitve je obvezen, ker PHP php.ini bere samo ob zagonu.
Skrajšanje glav Server v Nginx in Apache
Nginx svojo različico privzeto navaja v glavi Server in na straneh z napakami. Z server_tokens off; ostane samo ime izdelka. Dodatno je mogoče glavo X-Powered-By, ki jo nastavi aplikacija sama, odfiltrirati s fastcgi_hide_header. Po dokumentaciji Nginx sam od sebe skrije samo Status in X-Accel-…, ne pa X-Powered-By.
# v bloku http, velja za vse spletne strani
server_tokens off;
fastcgi_hide_header X-Powered-By;
V Apache ServerTokens upravlja glavo Server in hkrati vrstico z različico pod stranmi z napakami. Nastavitev po dokumentaciji Apache velja samo za ves strežnik, ne za posamezen VirtualHost. Ker odgovori PHP-FPM prek mod_proxy_fcgi pristanejo v drugi tabeli glav kot odgovori samega strežnika, odstranitev nastavite v obeh različicah.
# konfiguracija za ves strežnik, npr. /etc/apache2/conf-available/security.conf
ServerTokens Prod
ServerSignature Off
# potrebuje mod_headers
<IfModule mod_headers.c>
Header unset X-Powered-By
Header always unset X-Powered-By
</IfModule>
Konfiguracijo pred ponovnim nalaganjem preverite z nginx -t oziroma apachectl configtest. Kako prek glav dejavno vklopite zaščito za obiskovalce, na primer s HSTS ali Content-Security-Policy, opisuje vodnik Varnostne glave za spletne strani.
Tako od zunaj preverite rezultat
Po prehodu preverite vsako domeno posebej, po možnosti tudi stran z napako. Naslednji ukazi pošiljajo samo običajne zahteve na vaše lastne spletne strani:
# Glave začetne strani
curl -sI https://www.example.de/ | grep -iE '^(server|x-powered-by):'
# Glave neobstoječe strani
curl -sI https://www.example.de/gibt-es-nicht-4711 | grep -iE '^(server|x-powered-by):'
Pričakovana je glava Server brez številke različice in brez X-Powered-By. Če tam še vedno piše različica PHP, je običajno aktivna druga php.ini ali pa storitev še ni bila znova zagnana. Če je pred strežnikom CDN, dodatno preverite izvorni strežnik neposredno, če je dosegljiv.
Različico PHP vseeno zabeležite interno: v inventarju strežnikov, s stanjem paketa in datumom zadnjega preverjanja. Stanje popravkov dokazujete prek strežnika, kot je opisano v Pravilno preverjanje različice PHP in stanja popravkov.
Kaj skrivanje prinese in česa ne
Pošteno umeščen je izklop podatkov o različicah majhen ukrep z majhnim naporom. Zmanjša verjetnost, da se pojavite v ciljnih iskanjih po določenih različicah, in zmanjša informacije, ki jih napadalec dobi brez truda.
Ne ščiti pa pred samodejnimi napadi, ki svoje zahteve preprosto pošljejo na vsak dosegljiv strežnik. Kako taka množična skeniranja potekajo, opisuje prispevek Množična skeniranja za nepopravljen PHP. Proti PHP2Shell pomaga samo posodobitev na PHP 8.5.12, 8.4.27, 8.3.36 oziroma 8.2.35 ali potrjen backport, ki mu sledi ponovni zagon vseh procesov PHP.
Stranski učinek pa je izrazito koristen: kdor podatke o različicah navzven izklopi, mora svoje različice interno urejeno zajeti. V razmerah, kot je PHP2Shell, prav ta pregled odloča, kako hitro veste, kateri strežniki so prizadeti.
Skrivanje je zato smiselno kot del osnovnega utrjevanja, ne kot posamezen ukrep. Sodi na isti kontrolni seznam kot izklopljen izpis napak, izbrisane testne datoteke in zaklenjene konfiguracijske vrednosti.
Kako PHP SOS pomaga konkretno?
- Zajem mest najdbe: glave, strani z napakami in spletni koren vseh domen preverimo za podatke o različicah in pozabljene testne datoteke.
- Prilagoditev konfiguracije:
expose_php, glave strežnika in filtre glav nastavimo v vsaki različici PHP in vsakem spletnem strežniku ter storitve nadzorovano znova zaženemo. - Notranji dokaz stanja popravkov: različice in stanja paketov dokumentiramo tam, kamor sodijo, v inventar namesto v glavo HTTP.
- Vgraditev v utrjevanje: ukrep je del našega utrjevanja strežnikov za spletne strežnike PHP.
Pogosta vprašanja
Ali expose_php = Off naredi moj strežnik varen?
Ne. Nastavitev iz glave HTTP odstrani samo navedbo različice. Ranljiva različica PHP ostane ranljiva, samodejni napadi pa svoje zahteve pogosto tako ali tako preizkusijo na vsakem dosegljivem strežniku. Napadalcem pa vzame preprosto predizbiro in zmanjša vidnost v iskalnikih za strežnike.
Ali lahko expose_php nastavim v poolu FPM ali prek .htaccess?
Po priročniku PHP je expose_php mogoče spreminjati samo v php.ini. Vrednost zato nastavite v php.ini vsakega spletnega SAPI in nato znova zaženite PHP-FPM ali Apache.
Zakaj kljub expose_php = Off še vidim X-Powered-By?
Takrat glavo običajno sama nastavi aplikacija ali ogrodje ali pa je aktivna druga php.ini. Glavo dodatno odstranite v spletnem strežniku: s fastcgi_hide_header v Nginx ali Header unset v Apache.
Kako preverim stanje popravkov, če različica ni več vidna?
Prek samega strežnika: upravljalnik paketov, dnevnik sprememb paketa s številkami CVE in čas zagona procesov PHP. Navedba v glavi HTTP tako ali tako ni bila dokaz, saj distribucije backporte pogosto dostavljajo brez nove številke različice.