# expose_php ja Server-otsakkeet: versiotietojen piilotus

> expose_php, X-Powered-By ja Server-otsake: missä PHP ja verkkopalvelin paljastavat versionsa ja miten estätte sen php.ini-tiedostossa, Nginxissä ja Apachessa.

Lähde: https://phpsos.de/fi/blog/expose-php-versionsangaben/  
Tilanne: 25.10.2026  
Palveluntarjoaja: PHP SOS, PHP-hätäapu ja palvelimen tietoturva. Pikaapu WhatsAppilla: https://wa.me/491736494914?text=Hei%20PHP%20SOS%2C%20tarvitsemme%20apua%20PHP-palvelimemme%20kanssa.%20Yritys%3A%20%E2%80%A6%20Verkkosivusto%3A%20%E2%80%A6

**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ä](https://phpsos.de/fi/blog/phpinfo-dateien-entfernen/).

## 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/`.

```ini
; 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.

```nginx
# 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.

```apache
# 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](https://phpsos.de/fi/ratgeber/sicherheits-header/).

## 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:

```bash
# 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.

> **Vinkki:**
> 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](https://phpsos.de/fi/php2shell/php-version-pruefen/).

## 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](https://phpsos.de/fi/blog/automatisierte-massenscans/). 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](https://phpsos.de/fi/leistungen/server-haertung/).


## 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.

## Lähteet

- [PHP-käsikirja: ydinasetukset (expose_php)](https://www.php.net/manual/en/ini.core.php)
- [Nginx: server_tokens (ngx_http_core_module)](https://nginx.org/en/docs/http/ngx_http_core_module.html)
- [Apache: ServerTokens ja ServerSignature](https://httpd.apache.org/docs/2.4/mod/core.html)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
