Lyhyesti: Asetuksella expose_php = Off tiedostossa php.ini otsake X-Powered-By: PHP/… katoaa. Siihen kuuluvat server_tokens off; Nginxissä sekä ServerTokens Prod ja ServerSignature Off Apachessa. Se ei tee palvelimesta turvallisempaa, mutta vie automatisoiduilta skannauksilta valmiin versiolistan. Oman päivitystilanne tarkistatte sen jälkeen pakettienhallinnan ja prosessien kautta, ette otsakkeista.
Käyntikortti jokaisessa vastauksessa
Joka halusi 21. lokakuuta 2026 jälkeen tietää, kuinka monella palvelimella näkyy yhä vanha PHP-versio, ei joutunut etsimään kauan. Monet verkkopalvelimet kertovat PHP-versionsa jokaisessa yksittäisessä vastauksessa, esimerkiksi muodossa X-Powered-By: PHP/8.2.20. Koko internetiä skannaavat hakupalvelut lukevat nämä tiedot mukana, ja Palo Alto Networksin Unit 42 laski PHP2Shellille yli 22,6 miljoonaa altistunutta, mahdollisesti haavoittuvaa instanssia.
Hyökkääjille tällainen tieto on oikotie. He voivat lajitella kohteita etukäteen sen sijaan, että kokeilisivat sokkona. Ylläpitäjille se on sen sijaan hyödytön, sillä se ei todista edes omaa päivitystilaa: jakelut toimittavat korjaukset usein backporttina ilman uutta versionumeroa.
Tämä kirjoitus näyttää, missä PHP ja verkkopalvelin paljastavat versiotietoja ja miten estätte ne. Se kertoo myös suoraan, mitä siitä on hyötyä ja mitä ei.
Missä versiotiedot kaikkialla esiintyvät
PHP-versio on vain yksi monista paikoista. Täydellinen katsaus kannattaa, koska yksi ainoa unohtunut paikka mitätöi muut toimenpiteet.
| Löytöpaikka | Esimerkki | Estäminen |
|---|---|---|
| PHP:n HTTP-otsake | X-Powered-By: PHP/8.3.x |
expose_php = Off tiedostossa php.ini |
| Verkkopalvelimen HTTP-otsake | Server: nginx/1.x tai Server: Apache/2.4.x (Debian) |
server_tokens off; tai ServerTokens Prod |
| Verkkopalvelimen virhesivut | versiorivi 404- tai 500-sivujen alla | samat asetukset, Apachessa lisäksi ServerSignature Off |
| Sovelluksen otsakkeet | kehysten omat X-Powered-By-tiedot |
fastcgi_hide_header tai Header unset |
| Tiedostot verkkojuuressa | phpinfo()-testitiedostot, readme- ja changelog-tiedostot |
poistakaa tai estäkää |
| PHP:n virheilmoitukset | polut ja versioyksityiskohdat selaimessa | display_errors = Off |
phpinfo()-testitiedostot ovat tässä hyökkääjille antoisin lähde. Ne paljastavat paitsi version myös koko asetuksen; lisää kirjoituksessa phpinfo()-tiedostot: miksi niiden on hävittävä.
expose_php pois tiedostossa php.ini
PHP-käsikirjan mukaan expose_php on oletuksena päällä ja muutettavissa vain tiedostossa php.ini, ei poolissa, ei .htaccess-tiedostolla eikä suoritusaikana. Asettakaa arvo siksi jokaisen verkkosivustoja tarjoilevan käyttötavan php.ini-tiedostossa, eli Debianilla ja Ubuntulla esimerkiksi hakemistossa /etc/php/<version>/fpm/ ja tarvittaessa /etc/php/<version>/apache2/.
; verkko-SAPI:n php.ini, käynnistäkää sen jälkeen PHP-FPM tai Apache uudelleen
expose_php = Off
Jos useita PHP-versioita pyörii rinnakkain, jokainen tarvitsee merkintänsä. Kyseisen palvelun uudelleenkäynnistys on pakollinen, koska PHP lukee php.ini-tiedoston vain käynnistyksessä.
Server-otsakkeiden lyhentäminen Nginxissä ja Apachessa
Nginx ilmoittaa versionsa oletuksena Server-otsakkeessa ja virhesivuilla. Asetuksella server_tokens off; jää vain tuotteen nimi. Lisäksi sovelluksen itse asettama X-Powered-By-otsake voidaan suodattaa pois komennolla fastcgi_hide_header. Nginxin dokumentaation mukaan Nginx piilottaa itsestään vain Status- ja X-Accel-…-otsakkeet, ei X-Powered-By-otsaketta.
# http-lohkossa, koskee kaikkia verkkosivustoja
server_tokens off;
fastcgi_hide_header X-Powered-By;
Apachessa ServerTokens ohjaa Server-otsaketta ja samalla versiriviä virhesivujen alla. Asetus on Apachen dokumentaation mukaan voimassa vain palvelinlaajuisesti, ei VirtualHostia kohden. Koska PHP-FPM-vastaukset mod_proxy_fcgi:n kautta päätyvät eri otsaketaulukkoon kuin palvelimen omat vastaukset, asettakaa poisto molempiin muotoihin.
# palvelinlaajuiset asetukset, esim. /etc/apache2/conf-available/security.conf
ServerTokens Prod
ServerSignature Off
# vaatii mod_headers
<IfModule mod_headers.c>
Header unset X-Powered-By
Header always unset X-Powered-By
</IfModule>
Tarkistakaa asetukset ennen uudelleenlatausta komennolla nginx -t tai apachectl configtest. Miten otsakkeiden kautta kytketään aktiivisesti suoja kävijöille, esimerkiksi HSTS:llä tai Content-Security-Policylla, kuvaa opas Verkkosivustojen tietoturvaotsakkeet.
Näin tarkistatte tuloksen ulkopuolelta
Tarkistakaa umpimähkäisen sijaan jokainen verkkotunnus erikseen muutoksen jälkeen, mieluiten myös yksi virhesivu. Seuraavat komennot lähettävät vain tavallisia pyyntöjä omille verkkosivustoillenne:
# Etusivun otsakkeet
curl -sI https://www.example.de/ | grep -iE '^(server|x-powered-by):'
# Olemattoman sivun otsakkeet
curl -sI https://www.example.de/gibt-es-nicht-4711 | grep -iE '^(server|x-powered-by):'
Odotettu tulos on Server-otsake ilman versionumeroa ja ei X-Powered-By-otsaketta. Jos siellä on yhä PHP-versio, käytössä on yleensä toinen php.ini tai palvelua ei ole vielä käynnistetty uudelleen. Jos palvelimen edessä on CDN, tarkistakaa lisäksi alkuperäispalvelin suoraan, jos se on saavutettavissa.
Pitäkää PHP-versio silti sisäisesti kirjattuna: palvelinluettelossanne, pakettitilan ja viimeisen tarkistuksen päivämäärän kanssa. Päivitystilan todistatte palvelimen kautta, kuten kuvataan kohdassa PHP-version ja päivitystilan oikea tarkistus.
Mitä piilottaminen tuo ja mitä ei
Rehellisesti arvioituna versiotietojen kytkeminen pois on pieni toimenpide pienellä vaivalla. Se vähentää todennäköisyyttä ilmestyä tiettyjä versioita etsiviin kohdennettuihin hakuihin ja vähentää tietoja, jotka hyökkääjä saa vaivatta.
Se ei kuitenkaan suojaa automatisoiduilta hyökkäyksiltä, jotka lähettävät pyyntönsä yksinkertaisesti jokaiselle saavutettavalle palvelimelle. Miten tällaiset massaskannaukset etenevät, kuvaa kirjoitus Massaskannaukset päivittämättömään PHP:hen. PHP2Shelliä vastaan auttaa vain päivitys versioon PHP 8.5.12, 8.4.27, 8.3.36 tai 8.2.35 tai vahvistettuun backportiin, jota seuraa kaikkien PHP-prosessien uudelleenkäynnistys.
Yksi sivuvaikutus on sen sijaan erittäin hyödyllinen: joka kytkee versiotiedot pois ulospäin, joutuu kirjaamaan versionsa sisäisesti kunnolla. PHP2Shellin kaltaisessa tilanteessa juuri tämä yleiskuva ratkaisee, kuinka nopeasti tiedätte, mitkä palvelimet ovat vaikutuksen alaisia.
Piilottaminen on siksi järkevää osana peruskoventamista, ei yksittäisenä toimenpiteenä. Se kuuluu samaan tarkistuslistaan kuin pois kytketyt virhetulosteet, poistetut testitiedostot ja lukitut asetusarvot.
Miten PHP SOS auttaa konkreettisesti?
- Löytöpaikkojen kartoitus: Tarkistamme kaikkien verkkotunnusten otsakkeet, virhesivut ja verkkojuuren versiotietojen ja unohtuneiden testitiedostojen varalta.
- Asetusten mukauttaminen: Asetamme
expose_php-arvon, Server-otsakkeet ja otsakesuodattimet jokaisessa PHP-versiossa ja jokaisessa verkkopalvelimessa ja käynnistämme palvelut hallitusti uudelleen. - Päivitystilan todistaminen sisäisesti: Dokumentoimme versiot ja pakettitilat siellä, minne ne kuuluvat, luettelossa HTTP-otsakkeen sijaan.
- Liittäminen koventamiseen: Toimenpide on osa PHP-verkkopalvelimien koventamistamme.
Usein kysytyt kysymykset
Tekeekö expose_php = Off palvelimestani turvallisen?
Ei. Asetus poistaa vain versiotiedon HTTP-otsakkeesta. Haavoittuva PHP-versio pysyy haavoittuvana, ja automatisoidut hyökkäykset kokeilevat pyyntöjään usein joka tapauksessa jokaisella saavutettavalla palvelimella. Ne kuitenkin vievät hyökkääjiltä helpon esivalinnan ja vähentävät näkyvyyttä palvelimia etsivissä hakukoneissa.
Voinko asettaa expose_php-asetuksen FPM-poolissa tai .htaccess-tiedostolla?
PHP-käsikirjan mukaan expose_php on muutettavissa vain tiedostossa php.ini. Asettakaa arvo siksi jokaisen verkko-SAPI:n php.ini-tiedostossa ja käynnistäkää sen jälkeen PHP-FPM tai Apache uudelleen.
Miksi näen X-Powered-By-otsakkeen expose_php = Off -asetuksesta huolimatta?
Silloin yleensä sovellus tai kehys asettaa otsakkeen itse, tai käytössä on toinen php.ini. Poistakaa otsake lisäksi verkkopalvelimessa: Nginxissä komennolla fastcgi_hide_header, Apachessa komennolla Header unset.
Miten tarkistan päivitystilani, jos versio ei enää näy?
Palvelimen itsensä kautta: pakettienhallinta, pakettien muutosloki CVE-numeroineen ja PHP-prosessien käynnistysaika. HTTP-otsakkeen tieto ei ollut muutenkaan todiste, koska jakelut asentavat backportit usein ilman uutta versionumeroa.