Takaisin tietokeskukseen
HTTP-tietoturvaotsikoiden vahvistaminen: Vaiheittainen opas toteutukseen
guides FortifyNet Security Team 15 min8/28/2026

HTTP-tietoturvaotsikoiden vahvistaminen: Vaiheittainen opas toteutukseen

F-luokituksesta vahvistettuun A-luokkaan: ota käyttöön HSTS, nosniff, kehyssuojaus ja Permissions-Policy välittömästi, ja julkaise Content-Security-Policy kolmessa turvallisessa vaiheessa — nginx- ja Apache-konfiguraatioiden avulla.

Suorita sama tarkistus heti — ilmaiseksi

Anna verkkotunnuksesi ja saat 9-kohdan auditoinnin — DNS, SPF/DKIM/DMARC, SSL, tietoturvaotsikot, dark web -altistus — 60 sekunnissa.

Ei rekisteröitymistä · <60s · GDPR/EU-käsittely

HTTP-tietoturvaotsikot ovat halvin tietoturvatoimi, jonka tulet koskaan toteuttamaan: muutama vastausotsikko, joka asetetaan kerran verkkopalvelimelle tai CDN-palveluun, ohjeistaa jokaista vierailevaa selainta torjumaan kokonaisia hyökkäysluokkia — clickjacking, protokollan alentaminen (protocol downgrade), MIME-sniffaus, sivustojen väliset tietovuodot ja suuri osa sivustojen välisestä skriptauksesta (XSS). Silti valtaosa verkkosivustoista toimii yhä ilman niitä tai blogikirjoituksista kopioiduilla arvoilla, jotka rikkovat toiminnallisuutta hiljaisesti.

Tämä opas opastaa IT-päällikköä tuotantosivuston otsikoiden täydellisessä, vaiheittaisessa vahvistamisessa: mitä kukin otsikko tekee, tarkat arvot käyttöönottoon, kuinka Content-Security-Policy julkaistaan rikkomatta sivustoa, verkkopalvelimen konfigurointi nginxille ja Apachelle sekä kuinka lopputulos varmistetaan. Varaa työhön yksi työpäivä jaettuna kahden tai kolmen viikon aikavälille (CSP report-only -jakso vie suurimman osan ajasta).

Koodia näytöllä pimeässä huoneessa

Kuinka otsikot suojaavat käyttäjiä

Jokainen tämän oppaan otsikko on palvelimesi antama ohje vierailijan selaimelle. Selain pakottaa sen paikallisesti — laitteita, agentteja tai koodimuutoksia ei tarvita:

   Palvelimesi                          Vierailijan selain
   -----------                          -----------------
   HTTP/1.1 200 OK
   Strict-Transport-Security  ------>   "Älä lataa tätä sivustoa enää koskaan HTTP:llä"
   Content-Security-Policy    ------>   "Suorita skriptejä vain näistä alkuperistä"
   X-Frame-Options            ------>   "Kieltäydy renderöimästä tätä sivustoa iframe-elementissä"
   X-Content-Type-Options     ------>   "Älä koskaan arvaa tiedostotyyppejä"
   Referrer-Policy            ------>   "Älä vuoda täysiä URL-osoitteita muille sivustoille"
   Permissions-Policy         ------>   "Tämä sivusto ei saa käyttää kameraa/mikrofonia/sijaintia"

Koska täytäntöönpano tapahtuu selaimessa, otsikot suojaavat käyttäjiäsi, vaikka hyökkäys ei koskettaisi palvelintasi lainkaan — esimerkiksi kalastelusivusto, joka kehyksittää kirjautumislomakkeesi, tai injektoitu mainosskripti, joka varastaa lomakedataa.

Vaihe 1 — Perustaso: mittaa ennen kuin muutat mitään

Aja sivustosi otsikkoskannerin läpi — FortifyNetin ilmainen tietoturvaotsikoiden tarkistaja pisteyttää jokaisen otsikon ja näyttää yhden rivin korjauksen, ja securityheaders.com on hyvä toinen mielipide. Tallenna tulos. Tyypillinen vahvistamaton sivusto saa arvosanan F, kun käytössä on vain Server ja X-Powered-By — jotka molemmat vuotavat tietoja suojauksen sijaan.

Kartoita myös mitä sivusto todella lataa. Avaa selaimen kehitystyökalujen Network-välilehti viidellä tärkeimmällä sivullasi ja merkitse ylös jokainen kolmannen osapuolen alkuperä: analytiikka, fontit, tagien hallintatyökalut, chat-widgetit, maksujen iframe-elementit ja video-upotukset. Tästä listasta tulee CSP-sallittujen listasi vaiheessa 4.

Vaihe 2 — Ota viisi turvallista otsikkoa käyttöön välittömästi

Viisi otsikkoa ovat käytännössä riskittömiä lähes kaikille sivustoille ja ne tulisi julkaista ensimmäisessä muutosikkunassa.

Strict-Transport-Security (HSTS)

Pakottaa HTTPS-yhteyden jokaiseen tulevaan vierailuun, mikä torjuu SSL-stripping-hyökkäykset julkisessa Wi-Fi-verkossa.

Strict-Transport-Security: max-age=31536000; includeSubDomains

Aloita max-age=31536000 (yksi vuosi) vain, jos kaikki alidomainit käyttävät jo HTTPS-yhteyttä; muussa tapauksessa aloita max-age=86400 ja jätä includeSubDomains pois, ja laajenna myöhemmin. Kun tilanne on vakaa, harkitse HSTS preload -ominaisuutta — koodaus suoraan selaimiin poistaa ensimmäisen vierailun haavoittuvuuden, mutta se on käytännössä peruuttamaton, joten kohtele preloadia yksisuuntaisena porttina.

X-Content-Type-Options

X-Content-Type-Options: nosniff

Estää selaimia "haistelemasta" tiedostotyyppejä, mikä estää käyttäjän lataaman tekstitiedoston suorittamisen skriptinä. Ei ole mitään legitiimiä syytä jättää tätä pois.

X-Frame-Options

X-Frame-Options: DENY

Estää clickjacking-hyökkäykset — hyökkääjä peittää todellisen, kehyksitetyn sivustosi näkymättömillä painikkeilla. Käytä SAMEORIGIN-arvoa, jos sivustosi kehyksittää itseään legitiimisti (jotkut hallintapaneelit ja esikatselutoiminnot tekevät niin). Moderni CSP frame-ancestors korvaa tämän otsikon, mutta säilytä molemmat vanhempia selaimia varten.

Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin

Varmistaa, että linkit ulkoisille sivustoille paljastavat vain alkuperäsi (https://example.com) eivätkä koko URL-osoitetta — joka voi sisältää hakutermejä, tiliosoitteita tai nollaustunnuksia. Tämä arvo on myös modernien selainten oletus, mutta sen asettaminen eksplisiittisesti takaa sen kaikkialla.

Permissions-Policy

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Ilmoittaa, mitä tehokkaita selainominaisuuksia sivusto (ja mikä tahansa injektoitu skripti) saa käyttää. Kiellä kaikki, mitä et käytä; tällöin kompromisoitu kolmannen osapuolen skripti ei voi hiljaisesti pyytää pääsyä kameraan. Lisää ominaisuuksia takaisin (esim. payment=(self "https://js.stripe.com")) vain siellä, missä niitä todella tarvitaan.

Vaihe 3 — Poista vuotavat otsikot

Konfiguraatiota muokatessasi poista turhat oletukset: Server-versiomerkkijonot ja X-Powered-By. Ne eivät tarjoa mitään toiminnallisuutta ja antavat hyökkääjille tarkan ohjelmistoversion CVE-täsmäystä varten. Nginxissä: server_tokens off;. Apachessa: ServerTokens Prod ja ServerSignature Off. PHP:lle: expose_php = Off.

Vaihe 4 — Content-Security-Policy, vaiheittainen tapa

CSP on tehokkain otsikko — ja ainoa, joka voi rikkoa sivustosi, jos se otetaan käyttöön huolimattomasti. Älä koskaan kopioi CSP-otsikkoa toiselta sivustolta. Noudata sen sijaan tätä kolmivaiheista prosessia.

Vaihe A: Vain raportointi (1–2 viikkoa)

Ota käytäntö käyttöön Content-Security-Policy-Report-Only -tilassa. Selaimet arvioivat sen ja raportoivat rikkomuksista, mutta eivät estä mitään:

Content-Security-Policy-Report-Only: default-src 'self';
  script-src 'self' https://www.googletagmanager.com https://js.stripe.com;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' data: https:;
  frame-src https://js.stripe.com https://www.youtube-nocookie.com;
  connect-src 'self' https://www.google-analytics.com;
  frame-ancestors 'none';
  report-uri /csp-report

Rakenna sallittujen lista vaiheessa 1 tekemäsi inventaarion pohjalta. Osoita report-uri pieneen päätepisteeseen (tai isännöityyn palveluun) ja anna todellisen liikenteen testata jokainen sivu, mukaan lukien kassa ja harvoin vieraillut tilisivut, ainakin viikon ajan.

Vaihe B: Korjaa rikkomukset

Tarkista raportit ja kehitystyökalujen konsoli. Tavallisia löydöksiä:

RikkomusSyyKorjaus
inline script estettyonclick= käsittelijät, inline script -tagitsiirrä ulkoisiin tiedostoihin tai lisää nonce-arvot
eval estettyvanhat kirjastot, jotkut tagien hallintatyökalutpäivitä kirjasto; vältä 'unsafe-eval'
tuntematon alkuperäskripti, joka lataa skriptinlisää alkuperä tai poista widget
data: fontCSS:ään upotetut kuvakefontitsalli font-src data: tai vaihda SVG-ikoneihin

Skriptien kultainen standardi on noncet: palvelin luo satunnaisen arvon per vastaus, lisää sen otsikkoon (script-src 'nonce-R4nd0m') ja jokaiseen legitiimiin skriptitagiin. Injektoiduilta skripteiltä puuttuu nonce, joten ne estetään. 'strict-dynamic' (CSP Level 3) antaa nonce-hyväksytyn skriptin ladata omia riippuvuuksiaan — tämä on Googlen suosittelema malli ja se pienentää sallittujen listaa dramaattisesti.

Hyväksy 'unsafe-inline' tyyleille, jos sen poistaminen vaatii kohtuutonta työtä — inline CSS:n käytännön riski on paljon pienempi kuin inline JS:n. Älä hyväksy 'unsafe-inline' skripteille; se poistaa otsikon pääasiallisen arvon.

Vaihe C: Pakottaminen

Nimeä otsikko uudelleen Content-Security-Policy-muotoon, pidä raportointipäätepiste aktiivisena pysyvästi ja tarkkaile ensimmäiset 48 tuntia. Mikä tahansa regressio on yhden konfiguraatiorivin päässä palauttamisesta Report-Only-tilaan.

Vaihe 5 — Verkkopalvelimen konfigurointi

Aseta otsikot yhdessä keskeisessä paikassa — verkkopalvelimessa tai CDN-palvelussa — ei sovelluskohtaisesti, jotta jokainen vastaus (mukaan lukien virhesivut ja staattiset tiedostot) on suojattu.

nginx (server-lohkon sisällä; always-määre on vaadittu, jotta otsikot liitetään myös 4xx/5xx-vastauksiin):

server_tokens off;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; ..." always;

Varo klassista nginx-ansaa: add_header-direktiivejä ei peritä, jos location-lohko määrittää oman add_header-rivinsä. Pidä ne kaikki server-tasolla tai toista koko sarja.

Apache (vhost- tai .htaccess-tiedostossa, kun mod_headers on käytössä):

ServerTokens Prod
ServerSignature Off
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy "default-src 'self'; ..."

Käytä CDN-palveluissa (Cloudflare, CloudFront, Vercel, Netlify) niiden vastausotsikkomuunnoksia, jotta reunapalvelin soveltaa saman sarjan välimuistivastauksiin.

Vaihe 6 — Varmista ja varmista uudelleen

Jokaisen muutoksen jälkeen: päivitä sivu pakotetusti (hard-refresh) kehitystyökalut auki ja lue todelliset vastausotsikot; aja sitten otsikkotarkistaja uudelleen ja vertaa sitä vaiheen 1 perustasoon. Hyvin suojattu sivusto saavuttaa A-luokituksen.

Otsikot "mätänevät". Uudelleensuunnittelu lisää widgetin, jonka CSP estää; muutto uuteen kuormantasaajaan saattaa poistaa koko sarjan hiljaisesti. Aseta varmistus aikatauluun — FortifyNetin jatkuva seuranta tarkistaa otsikot uudelleen ja hälyttää muutoksista, mikä on juuri se "konfiguraation ryöminnän" vikamoodi, jonka manuaaliset prosessit ohittavat.

Evästeiden vahvistaminen — unohdetut vastausotsikot

Istuntoevästeet asetetaan myös vastausotsikoilla, ja vahvistettu otsikkosetti on epätäydellinen ilman niitä. Kolme attribuuttia jokaiselle Set-Cookie-otsikolle:

Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax; Path=/
  • Secure — evästettä ei koskaan lähetetä suojaamattomana HTTP-yhteyden yli. Kun HSTS on käytössä, tämä sulkee tietoturva-aukon kokonaan.
  • HttpOnly — JavaScript ei voi lukea evästettä, joten edes onnistunut XSS ei voi viedä istuntotunnusta suoraan.
  • SameSite=Lax (tai Strict) — selain pidättäytyy lähettämästä evästettä sivustojen välisissä pyynnöissä, mikä neutraloi suurimman osan CSRF-hyökkäyksistä ilman koodimuutoksia. Käytä SameSite=None; Secure vain evästeille, joiden on aidosti kuljettava sivustojen välillä (upotetut widgetit, SSO-kulkut).

Harkitse evästeiden etuliitteitä syvällistä suojausta varten: selain hyväksyy __Host-alkuisen evästeen (esim. __Host-session) vain, jos se on Secure, sillä ei ole Domain-attribuuttia ja Path=/ — mikä tekee kompromisoidulle alidomainille mahdottomaksi kirjoittaa sen päälle.

Sivustojen välinen eristäminen — COOP, CORP ja CORS-järki

Kolme uudempaa otsikkoa ohjaavat selaimen tasolla, kuinka sivustosi on vuorovaikutuksessa muiden alkuperien kanssa:

OtsikkoSuositeltu arvoMitä se estää
Cross-Origin-Opener-Policysame-originmuut sivustot, joilla on skriptattava viittaus ikkunaasi (tabnabbing, XS-Leaks)
Cross-Origin-Resource-Policysame-origin (tai same-site)muiden alkuperien upotukset resursseistasi (tietovarkaudet upotuksen kautta)
Cross-Origin-Embedder-Policyrequire-corp (edistynyt)sellaisten cross-origin-resurssien lataaminen, jotka eivät ole itse suostuneet siihen

COOP: same-origin ja CORP: same-origin ovat turvallisia useimmille sivustoille ja ne kannattaa ottaa käyttöön samassa muutoksessa kuin vaihe 2. COEP on tiukempi — se rikkoo kaikki cross-origin-kuvat tai skriptit, jotka eivät itse lähetä CORP-otsikoita — joten ota se käyttöön vain, jos tarvitset sivustojen välistä eristämistä (esim. SharedArrayBuffer) ja testaa ensin Report-Only-tilassa (Cross-Origin-Embedder-Policy-Report-Only on olemassa juuri tätä varten).

Tarkista tässä yhteydessä myös CORS: Access-Control-Allow-Origin: * API-rajapinnassa, joka käyttää evästeitä tai palauttaa käyttäjädataa, on vakava haavoittuvuus, ei mukavuustekijä. Salli vain tietyt alkuperät, äläkä koskaan heijasta pyynnön Origin-otsikkoa takaisin validoimattomana.

Arkaluontoisten vastausten välimuisti

Vahvistamiseen kuuluu myös varmistaminen, ettei yksityistä dataa tallenneta paikkoihin, joista et voi poistaa sitä. Kaikissa todennetuissa tai henkilötietoja sisältävissä vastauksissa:

Cache-Control: no-store

no-store päihittää vanhemmat Pragma- ja Expires-yhdistelmät ja estää sekä selaimen että välikäsien välimuistitallennuksen. Klassinen virhe: uloskirjautumispainike toimii, mutta "takaisin"-painike näyttää silti tilisivun selaimen välimuistista — no-store todennetuilla sivuilla korjaa tämän. Käytä pitkäikäistä välimuistia (Cache-Control: public, max-age=31536000, immutable) sormenjäljitetyille staattisille tiedostoille; nämä kaksi käytäntöä voivat elää rinnakkain reittikohtaisesti.

Huomioita SPA-sovelluksille ja kehyksille

Single-page-sovellukset muuttavat CSP-laskentaa hieman:

  • HTML-kuori ladataan kerran, joten noncet on luotava per vastaus reunapalvelimessa tai palvelimessa — staattinen sivustogeneraattori, joka leipoo yhden noncen build-vaiheessa, ei tarjoa tietoturvaa. Jos sivusto on täysin staattinen, käytä noncejen sijaan tiettyjen inline-skriptien tiivisteitä (sha256-…).
  • Hydraatio-kehykset (Next.js, Nuxt) upottavat tilan skriptitageina; molemmat tukevat noncen välitystä middlewaren kautta — käytä kehyksen dokumentoitua CSP-integraatiota sen sijaan, että taistelisit sitä vastaan.
  • connect-src on SPA-sovelluksen aktiivisin direktiivi: jokainen API-alkuperä, websocket-päätepiste ja telemetria-vastaanottaja on listattava. Puuttuvat merkinnät epäonnistuvat hiljaisesti käyttäjille (pyynnöt estetään, ominaisuudet kuolevat) — tämä on toinen syy sille, miksi Report-Only-vaiheesta ei voi neuvotella.
  • Käytä selainten kuluttamille API-rajapinnoille samoja perusotsikoita: nosniff, no-store missä tarpeen, ja rajoittava CSP (default-src 'none') missä tahansa päätepisteessä, joka voitaisiin avata suoraan selainikkunassa.

Varmistaminen komentoriviltä

Skannerit ovat käteviä, mutta sinun tulee osata varmistaa otsikot myös suoraan — erityisesti debugattaessa sitä, miksi otsikko on läsnä yhdellä reitillä mutta puuttuu toiselta (nginx-perintäansa, CDN-muunnos, jota sovelletaan vain yhteen polkukuvioon, tai sovelluskehys, joka ohittaa palvelimen asetukset). Käytä curl-komentoa pääpyyntölipulla (iso I) tai selaimen kehitystyökalujen Network-paneelia ja lue raa'at vastausotsikot kolmelle URL-osoitteelle: kotisivulle, todennetun alueen reitille ja sivulle, jota ei ole olemassa. Terve vastaus näyttää tältä:

HTTP/2 200
content-security-policy: default-src 'self'; ...
permissions-policy: camera=(), microphone=(), geolocation=()
referrer-policy: strict-origin-when-cross-origin
strict-transport-security: max-age=31536000; includeSubDomains
x-content-type-options: nosniff
x-frame-options: DENY

Tarkista kaikki kolme tapausta: kotisivu, todennetun alueen reitti ja 404-virhesivu. Toista tarkistus sekä HTTP- että HTTPS-yhteydellä, sekä www- ja domain-variantteilla, jos molemmat ovat käytössä — uudelleenohjaukset tulevat usein eri konfiguraatiolohkosta, joka ei sisällä mitään vahvistuksia, ja SSL-stripping-hyökkäys alkaa juuri tuosta suojaamattomasta ensihypystä. Virhesivu on toinen klassinen aukko — kehykset palvelevat virhevastaukset usein eri koodipolun kautta, joka ohittaa middlewaren, ja sivustoasi tutkiva hyökkääjä näkee pääosin virhesivuja. Jos 404-sivulta puuttuvat kotisivun otsikot, sarjaa ei ole sovellettu tarpeeksi keskitetysti; siirrä se palvelin- tai reunatasolle.

Kaksi muuta automatisoinnin arvoista tapaa:

  • CI-tarkistus: viiden rivin skripti käyttöönottoputkessa, joka käyttää curl-komentoa staging-URL-osoitteeseen ja estää buildin, jos odotettu otsikko puuttuu. Tämä nappaa "uusi kuormantasaaja poisti kaiken" -regression ennen kuin se päätyy tuotantoon.
  • Muutoshälytykset tuotannossa: ulkoinen valvonta, joka lukee live-otsikkosarjan aikataulun mukaan ja hälyttää poikkeamista — tämä on osa FortifyNetin jatkuvaa valvontaa, ja näin opit regressioista, joita CI ei nähnyt, kuten suoraan palveluntarjoajan hallintapaneelista tehty CDN-konfiguraatiomuutos.

Yleisiä myyttejä ja virheitä

  • "Meillä on WAF, otsikot ovat tarpeettomia." WAF tarkastaa palvelimellesi tulevan liikenteen; otsikot ohjaavat sitä, mitä selain tekee sivuillasi, mukaan lukien hyökkäykset, jotka eivät kosketa infrastruktuuriasi lainkaan. Ne ovat toisiaan täydentäviä kerroksia.
  • "X-XSS-Protection pitäisi olla päällä." Ei — otsikko on vanhentunut; auditoija, joka huomauttaa sen puuttumisesta, on vanhentunut. Modernit selaimet poistivat sen kontrolloiman XSS-tarkistajan, ja vanhoissa selaimissa se toi mukanaan haavoittuvuuksia. Aseta se arvoon 0 tai jätä se kokonaan pois; CSP on sen korvaaja.
  • "CSP rikkoi sivuston kerran, joten poistimme sen." Epäonnistuminen johtui Report-Only-vaiheen ohittamisesta, ei CSP:stä itsestään. Toista vaiheittainen prosessi.
  • "A-luokitus tarkoittaa turvallista." Otsikot ovat yksi kerros. A-luokiteltu sivusto, jossa on päivittämätön CMS, on yhä yhden pluginin CVE-haavoittuvuuden päässä kompromisoitumisesta — minkä vuoksi otsikkoskannaus on vain yksi testi muiden joukossa koko FortifyNet-auditoinnissa.

Käyttöönoton tarkistuslista

  • Perustason skannaus tallennettu; kolmannen osapuolen alkuperien inventaario valmis
  • HSTS, nosniff, X-Frame-Options, Referrer-Policy, Permissions-Policy julkaistu
  • Server/X-Powered-By -versiovuodot poistettu
  • CSP käytössä Report-Only-tilassa ja raportointipäätepiste määritetty
  • Rikkomukset lajiteltu; noncet käytössä skripteille; ei 'unsafe-inline' script-src-direktiivissä
  • CSP pakotettu; frame-ancestors asetettu; raportointi pidetty päällä
  • Otsikot asetettu keskitetysti (palvelin/CDN), always/Header always -asetusta käytetty
  • Uudelleenskannaus näyttää arvosanan A; jatkuva valvonta käytössä

Lähteet

#deep-guide#headers#csp#hsts

Tarkista verkkotunnuksesi nyt

Suorita ilmainen tietoturvatarkastus ja katso onko verkkotunnuksellasi artikkelin ongelmia.

Eväste-asetukset

Käytämme evästeitä parantaaksemme kokemustasi. Voit valita mitkä evästeet hyväksyt.