# Security Header -otsakkeet verkkosivustoille: tietoturvaotsakkeiden oikea asetus

> Security Header -otsakkeiden käyttöönotto: CSP, HSTS, X-Content-Type-Options ja muut esimerkein Nginxille ja Apachelle sekä tarkistus ja tyypilliset virheet.

Lähde: https://phpsos.de/fi/ratgeber/sicherheits-header/  
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:** Security Header -otsakkeet ovat verkkopalvelimen ohjeita selaimelle, jotka suojaavat kävijöitä hyökkäyksiltä kuten Cross-Site Scripting, Clickjacking ja salaamattomat yhteydet. Tärkeimmät ovat HSTS, Content-Security-Policy, X-Content-Type-Options, suoja vieraita kehyksiä vastaan, Referrer-Policy ja Permissions-Policy. Ne ovat järkevää koventamista, mutta eivät korvaa palvelimen päivityksiä.

## Mitä Security Header -otsakkeet tekevät ja mitä eivät

Jokaisen sivukutsun yhteydessä verkkopalvelin lähettää sisällön lisäksi myös otsakkeita. Osa niistä ohjaa selaimen tietoturvatoimintoja. Niillä voi esimerkiksi määrätä, että sivu ladataan vain HTTPS:n kautta tai että selain ei suorita skriptejä vierailta verkkotunnuksilta.

Ylläpitäjälle luokittelu on tärkeä: otsakkeet suojaavat ensisijaisesti kävijöitä, esimerkiksi istuntojen siepkaukselta tai manipuloiduilta lomakkeilta. Ne eivät sulje palvelimen aukkoja. Heikkous PHP:ssä, CMS:ssä tai laajennuksessa säilyy, vaikka otsakkeet olisi asetettu kuinka hyvin tahansa. Yhdessä siistin koodin kanssa ne kuitenkin rajoittavat monen virheen seurauksia selvästi.

## Tärkeimmät Security Header -otsakkeet yleiskuvana

| Otsake | Tarkoitus | Suositus lähtökohdaksi |
|---|---|---|
| Strict-Transport-Security (HSTS) | pakottaa HTTPS:n tuleviin kutsuihin | `max-age=31536000; includeSubDomains` |
| Content-Security-Policy (CSP) | määrittää sallitut lähteet skripteille, kuville, kehyksille | yksilöllinen, aluksi Report-Only |
| X-Content-Type-Options | estää selainta arvaamasta tiedostotyyppejä | `nosniff` |
| X-Frame-Options tai CSP frame-ancestors | estää upottamisen vieraille sivuille (Clickjacking) | `SAMEORIGIN` tai `frame-ancestors 'self'` |
| Referrer-Policy | rajoittaa, mikä osoite välitetään muille sivuille | `strict-origin-when-cross-origin` |
| Permissions-Policy | kytkee pois selaimen toimintoja kuten kamera tai sijainti | salli vain tarvittavat toiminnot |

HSTS kannattaa asettaa vasta, kun kaikki alidomainit ovat luotettavasti tavoitettavissa HTTPS:n kautta. Selain muistaa ohjeen annetun ajan; virhettä ei silloin voi perua heti. Aloittakaa tarvittaessa lyhyellä voimassaoloajalla ja pidentäkää sitä onnistuneiden testien jälkeen. Lisävalinta `preload` kirjaa verkkotunnuksen pysyvästi selainvalmistajien luetteloihin, ja se kannattaa asettaa vasta huolellisen tarkistuksen jälkeen.

Otsakkeet eivät myöskään ole ainoa paikka, jossa selain tarjoaa suojaa. Evästeillä pitäisi olla määreet `Secure`, `HttpOnly` ja `SameSite`, jotta istuntoja ei voi siepata salaamattomilla yhteyksillä tai skripteillä. Miten sen asetatte PHP:ssä, kuvataan istuntoja koskevassa oppaassa.

## Security Header -otsakkeiden asettaminen Nginxissä

Nginxissä otsakkeet kuuluvat kunkin verkkosivuston `server`-lohkoon. Lisäys `always` huolehtii siitä, että ne lähetetään myös virhesivuilla.

```nginx
server {
    # ...
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'" always;

    server_tokens off;
}
```

Nginxin erikoisuus: jos `location`-lohko asettaa omia `add_header`-käskyjä, `server`-lohkon otsakkeita ei oteta siellä mukaan. Tarkistakaa siksi myös alasivut ja staattiset tiedostot. Lisäkoventamista tälle yhdistelmälle kuvataan sivulla [Nginx ja PHP-FPM turvalliseksi](https://phpsos.de/fi/server/nginx-php-fpm/).

## Security Header -otsakkeiden asettaminen Apachessa

Apachessa tarvitsette moduulin `mod_headers`. Käskyt kuuluvat VirtualHostiin tai, jos siihen ei ole pääsyä, `.htaccess`-tiedostoon.

```apache
<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
    Header always set Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
</IfModule>

ServerTokens Prod
ServerSignature Off
```

`ServerTokens` ja `ServerSignature` kuuluvat pääasetuksiin. Ne estävät palvelinta kertomasta tarkkaa versiotaan vastauksissa ja virhesivuilla. PHP:lle saatte saman aikaan `php.ini`-tiedostossa asetuksella `expose_php = Off`.

## Content Security Policyn käyttöönotto vaiheittain

Content Security Policy on tehokkain mutta myös vaativin otsake. Se määrittää, mistä lähteistä skriptejä, tyylitiedostoja, kuvia, fontteja ja kehyksiä saa ladata. Jos lisätty skripti ladataan vieraalta verkkotunnukselta, selain estää sen.

Nykyaikaisilla verkkosivustoilla on usein upotettuna analytiikkatyökaluja, maksupalveluntarjoajia, karttapalveluita tai videoita. Liian tiukka linjaus lamauttaa silloin toimintoja. Edetkää siksi vaiheittain:

- Aloittakaa ensin otsakkeella `Content-Security-Policy-Report-Only`. Selain ilmoittaa rikkomuksista kehittäjäkonsolissa tai keräysosoitteeseen, mutta ei estä mitään.
- Kartoittakaa kaikki tarvittavat lähteet ja sallikaa ne kohdennetusti yleisten jokerimerkkien sijaan.
- Siirtäkää upotetut skriptit vaiheittain tiedostoihin tai varustakaa ne nonce-arvoilla, jotta `'unsafe-inline'` voidaan jättää pois.
- Siirtykää otsakkeeseen `Content-Security-Policy` vasta testivaiheen jälkeen, kun ilmoituksia ei enää tule odottamattomista kohdista.

> **Vinkki:**
> CSP täydentää siistiä escapointia koodissa, mutta ei korvaa sitä. Miten tulosteet suojataan PHP:ssä oikein, kerrotaan oppaassa [Cross-Site Scriptingin estäminen PHP:ssä](https://phpsos.de/fi/ratgeber/xss-php/).

## Otsakkeiden tarkistus ja tyypillisten virheiden välttäminen

Jokaisen muutoksen jälkeen kannattaa tarkistaa, saapuvatko otsakkeet todella perille. Se onnistuu ilman lisätyökaluja `curl`:lla:

```bash
# Testaa asetukset ja lataa uudelleen
nginx -t && systemctl reload nginx

# Näytä etusivun ja staattisen tiedoston otsakkeet
curl -sI https://www.example.de/ | grep -iE 'strict|content-security|x-content|x-frame|referrer|permissions|server'
curl -sI https://www.example.de/favicon.ico | grep -iE 'strict|x-content'
```

Tyypillisiä virheitä ovat kahteen kertaan asetetut otsakkeet, kun verkkopalvelin ja sovellus lähettävät samat otsakkeet, edeltävä CDN, joka poistaa tai ylikirjoittaa otsakkeita, sekä otsakkeet, jotka näkyvät vain etusivulla mutta eivät uudelleenohjauksissa tai virhesivuilla. Tarkistakaa lisäksi CMS:n tai tietoturvalaajennusten päivitysten jälkeen, ovatko otsakkeet muuttuneet.

Sopikaa siksi yksi paikka, jossa otsakkeita ylläpidetään, mieluiten verkkopalvelin tai edeltävä palvelu. Monet CMS-laajennukset tarjoavat myös asetuksia tietoturvaotsakkeille. Se on kätevää, mutta johtaa helposti kaksinkertaisiin tai ristiriitaisiin tietoihin, jos palvelin asettaa otsakkeita lisäksi. Yksittäisiin testeihin sopivat myös selaimen kehittäjätyökalut: verkko-välilehdellä näette jokaisen pyynnön vastausotsakkeet, ja konsoli näyttää Content Security Policyn rikkomukset.

## Miten PHP SOS auttaa konkreettisesti?

- Tarkistamme kaikkien verkkosivustojenne nykyiset otsakkeet, myös CDN:n ja välityspalvelimen takana, ja osoitamme aukot ja ristiriidat.
- Asetamme otsakkeet keskitetysti verkkopalvelimessa osana [palvelimen koventamista](https://phpsos.de/fi/leistungen/server-haertung/) ja testaamme etusivun, alasivut ja virhesivut.
- Otamme Content Security Policyn käyttöön Report-Only-tilassa, analysoimme ilmoitukset ja kytkemme sen päälle sovittuamme asiasta.
- Jos koodimuutokset eivät ole heti mahdollisia, täydennämme suojaa [WAF-säännöillä ja virtuaalisella korjauksella](https://phpsos.de/fi/leistungen/waf-virtuelles-patching/).


## Usein kysytyt kysymykset

**Mitä ovat Security Header -otsakkeet?**  
Security Header -otsakkeet ovat verkkopalvelimen vastauksen lisätietoja. Ne kertovat selaimelle esimerkiksi, että sivu ladataan vain HTTPS:n kautta, vieraita skriptejä ei suoriteta tai sivua ei näytetä vieraissa kehyksissä. Ne suojaavat ennen kaikkea kävijöitä.

**Suojaavatko Security Header -otsakkeet PHP2Shellilta?**  
Eivät. PHP2Shell on aukko PHP:ssä palvelimella, otsakkeet vaikuttavat kävijän selaimessa. PHP2Shelliä vastaan auttaa päivitys korjattuun PHP-versioon ja kaikkien worker-prosessien uudelleenkäynnistys. Otsakkeet ovat täydentävää koventamista muita hyökkäystyyppejä vastaan.

**Voiko Content Security Policy rikkoa verkkosivustoni?**  
Voi, liian tiukka linjaus estää tarvittavia skriptejä, fontteja tai upotettuja sisältöjä. Siksi se otetaan ensin käyttöön Report-Only-tilassa, ilmoitukset arvioidaan ja vasta sitten siirrytään täytäntöönpanoon.

**Onko X-XSS-Protection yhä järkevä?**  
Ei. Nykyiset selaimet eivät enää tulkitse tätä otsaketta, ja suositus on jättää se pois tai asettaa arvoon 0. Suojan Cross-Site Scriptingia vastaan tarjoavat siisti escapointi koodissa ja Content Security Policy.

## Lähteet

- [OWASP Cheat Sheet Series (HTTP Headers)](https://cheatsheetseries.owasp.org/)
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [BSI: suositukset verkkopalvelimille](https://www.bsi.bund.de/)
