Privacy & Security

HSTS instellen zonder jezelf buiten te sluiten

Een gefaseerd, omkeerbaar uitrolplan voor Strict-Transport-Security dat de privacy verbetert zonder dat één slecht certificaat een storing wordt.

The Wux Webtools Team The Wux Webtools Team 8 min lezen AI-ondersteund, door mensen beoordeeld
Illustration of a secure browser connection with redirect arrows and subdomain warning markers.
Inhoudsopgave
  1. HSTS is eenvoudig totdat het dat niet meer is
  2. Wat de HSTS-header echt doet
  3. De buitensluitingsscenario’s die je wilt vermijden
  4. 1. Een vergeten subdomein is niet klaar voor HTTPS
  5. 2. Een certificaat verloopt
  6. 3. Staging- of interne tools staan onder het productiedomein
  7. 4. Preload wordt behandeld als een gewone checkbox
  8. Een veilig uitrolplan
  9. Step 1: Audit elke hostname die je beheert
  10. Step 2: Repareer HTTPS voordat je HSTS toevoegt
  11. Step 3: Begin met een zeer korte max-age
  12. Step 4: Verhoog geleidelijk
  13. Step 5: Voeg includeSubDomains pas toe nadat de audit echt is
  14. Step 6: Behandel preload als een apart project
  15. Configuratievoorbeelden
  16. Nginx
  17. Apache
  18. CDN of edge-platform
  19. HSTS veilig terugdraaien
  20. Testchecklist voordat je uitrolt
  21. Het privacyargument voor HSTS

HSTS is eenvoudig totdat het dat niet meer is

HTTP Strict Transport Security, meestal afgekort tot HSTS, vertelt browsers: “gebruik voor deze site altijd HTTPS.” Zodra een browser de header via een geldige HTTPS-verbinding ontvangt, onthoudt hij de regel gedurende de periode die je opgeeft.

Dat is nuttig. Het voorkomt protocol-downgradeaanvallen, vermindert onbedoelde onveilige requests en voorkomt het ongemakkelijke moment waarop een gebruiker example.com typt en kort plain HTTP raakt voordat er wordt omgeleid.

Het is ook hardnekkig. Als je het verkeerde HSTS-beleid publiceert, kunnen browsers dat blijven afdwingen lang nadat je de header van je server hebt verwijderd. Zo sluiten teams zichzelf buiten: niet precies uit hun eigen adminpaneel, maar uit de browsers van gebruikers, subdomeinen, staging-systemen, legacy-endpoints en vergeten services die nog niet klaar zijn voor verplichte HTTPS.

Het doel is niet om HSTS te vermijden. Het doel is om het te implementeren als een migratie, niet als een schakelaar.

Wat de HSTS-header echt doet

Een typische HSTS-header ziet er zo uit:

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

Hij heeft drie belangrijke onderdelen:

  • max-age: hoe lang, in seconden, de browser HTTPS voor deze host moet afdwingen.
  • includeSubDomains: of de regel ook geldt voor elk subdomein.
  • preload: een signaal dat je het domein wilt laten opnemen in preload-lijsten van browsers.

De browser vertrouwt deze header alleen wanneer hij die via geldige HTTPS ontvangt. Als het certificaat ongeldig, verlopen of niet passend is, hoort de browser geen nieuw HSTS-beleid uit die response te accepteren.

Zodra het beleid is opgeslagen, worden toekomstige pogingen om http://example.com te bezoeken door de browser opgewaardeerd naar https://example.com voordat de request wordt verzonden. Dat is de privacywinst: de onveilige request verlaat het apparaat nooit.

De buitensluitingsscenario’s die je wilt vermijden

De meeste HSTS-fouten worden niet veroorzaakt door de hoofdwebsite. Ze gebeuren aan de randen.

1. Een vergeten subdomein is niet klaar voor HTTPS

includeSubDomains klinkt netjes, maar is absoluut. Als je het instelt op example.com, geldt het voor:

  • www.example.com
  • api.example.com
  • old-crm.example.com
  • printer-setup.example.com
  • staging.example.com
  • alles daaronder binnen dat domein

Als een van die hosts geen geldige HTTPS kan serveren, kunnen gebruikers met het HSTS-beleid in de cache ze niet meer via HTTP bereiken.

2. Een certificaat verloopt

Zonder HSTS klikken gebruikers soms door certificaatwaarschuwingen heen. Dat is geen goede beveiligingspraktijk, maar het gebeurt.

Met HSTS laten moderne browsers geen eenvoudige bypass van certificaatfouten toe voor die host. Dat is precies de bedoeling. Het betekent ook dat certificaatvernieuwing saai, gemonitord en getest moet zijn.

3. Staging- of interne tools staan onder het productiedomein

Interne tools onder *.example.com plaatsen kan pijnlijk worden zodra het hoofddomein includeSubDomains gebruikt. Als die tools self-signed certificaten, private certificate authorities, oude TLS-configuraties of helemaal geen HTTPS gebruiken, maakt HSTS die shortcut zichtbaar.

Dit is een reden waarom veel teams interne en experimentele systemen onder een apart domein houden met een eigen beveiligingsbeleid.

4. Preload wordt behandeld als een gewone checkbox

HSTS preload is niet zomaar nog een directive. Het betekent dat je domein in browsers kan worden meegeleverd als HTTPS-only voordat een gebruiker je site ooit heeft bezocht.

Dat sluit het gat van het “eerste bezoek”, maar is veel moeilijker terug te draaien. Verwijdering uit preload-lijsten kan weken of maanden duren voordat die gebruikers bereikt, afhankelijk van browser-releasecycli. Preload is geschikt voor stabiele, volwassen domeinen. Het is niet geschikt voor een site die zijn subdomeininventaris nog aan het ontdekken is.

Een veilig uitrolplan

Step 1: Audit elke hostname die je beheert

Voordat je includeSubDomains instelt, maak je een lijst van elke hostname onder het domein. DNS-records zijn een begin, maar niet het hele verhaal. Controleer CDN-configuraties, hostingdashboards, e-mailgerelateerde hostnames, oude marketingtools, storage buckets en interne documentatie.

Beantwoord voor elke hostname:

  • Serveert hij HTTP, HTTPS of beide?
  • Is het HTTPS-certificaat geldig en wordt het automatisch vernieuwd?
  • Leidt HTTP netjes om naar HTTPS?
  • Is hij bedoeld om publiek te zijn?
  • Is hij nog nodig?

Als je team al gewoonten heeft voor het debuggen van productieheaders, past dit vanzelf naast redirect- en headercontroles. We hebben die workflow behandeld in een kleine toolkit voor het debuggen van redirects en HTTP-headers in productie.

Step 2: Repareer HTTPS voordat je HSTS toevoegt

HSTS maakt een kapotte HTTPS-configuratie niet veilig. Het maakt HTTPS alleen verplicht.

Controleer voordat je het inschakelt:

  • TLS-certificaten dekken de juiste hostnames.
  • Certificaten worden automatisch vernieuwd.
  • HTTP leidt om naar HTTPS met waar mogelijk één nette sprong.
  • Canonical-host-redirects zijn consistent, bijvoorbeeld non-www naar www, of andersom.
  • Applicatie-assets zijn niet afhankelijk van onveilige http://-URL’s.

Mixed content komt minder vaak voor dan vroeger, maar verschijnt nog steeds in oude CMS-thema’s, analytics-snippets, embedded media en hard-gecodeerde afbeeldingspaden.

Step 3: Begin met een zeer korte max-age

Begin niet met één jaar. Begin met vijf minuten:

Strict-Transport-Security: max-age=300

Deploy dat alleen op de hostname die je test, meestal de canonical productiewebsite. Laat includeSubDomains voorlopig weg.

Test daarna in echte browsers en met command-line requests:

curl -I https://example.com

Je zou precies één Strict-Transport-Security-header moeten zien. Dubbele HSTS-headers van een appserver en een CDN zijn een veelvoorkomende bron van verwarring. Browsers passen doorgaans het effectieve beleid toe, maar mensen die een incident debuggen hebben geen behoefte aan ambiguïteit.

Step 4: Verhoog geleidelijk

Als er niets breekt, verhoog je de duur in stappen:

Strict-Transport-Security: max-age=86400

Daarna:

Strict-Transport-Security: max-age=604800

En daarna misschien:

Strict-Transport-Security: max-age=2592000

Een praktisch schema is:

  • 5 minuten
  • 1 dag
  • 1 week
  • 1 maand
  • 6 maanden of 1 jaar

Er is geen prijs voor haast. Het hele punt van een gefaseerde uitrol is dat je monitoring, support-inbox en edgecases tijd krijgen om je te vertellen wat je checklist heeft gemist.

Step 5: Voeg includeSubDomains pas toe nadat de audit echt is

Zodra elk publiek subdomein klaar is voor HTTPS, kun je dit overwegen:

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

Dit is het moment om conservatief te zijn. Als één legacy-service nog HTTP nodig heeft, voeg dan geen includeSubDomains toe aan het hoofddomein. Migreer die service, verplaats hem naar een ander domein, of accepteer dat je HSTS-beleid voorlopig smaller moet blijven.

Security headers moeten de werkelijkheid weerspiegelen. Ze moeten niet worden gebruikt als motiverende posters voor infrastructuur die je later hoopt te hebben.

Step 6: Behandel preload als een apart project

Overweeg preload alleen wanneer al het volgende waar is:

  • Het domein en alle subdomeinen ondersteunen geldige HTTPS.
  • HTTP leidt om naar HTTPS.
  • De HSTS-header gebruikt een max-age van minstens 31536000 seconden.
  • De header bevat includeSubDomains.
  • De header bevat preload.
  • Je weet zeker dat je nergens onder het domein plain HTTP nodig zult hebben.

Een preload-klare header ziet er zo uit:

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

Indienen bij de preload-lijst is een langetermijnverbintenis. Als de site een campagne-microsite, een tijdelijk productdomein of een domein met onduidelijke eigendomsgrenzen is, sla het dan over.

Configuratievoorbeelden

Nginx

Gebruik always zodat de header ook op foutresponses wordt verzonden:

add_header Strict-Transport-Security "max-age=300" always;

Nadat de uitrol stabiel is:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Apache

Met mod_headers ingeschakeld:

Header always set Strict-Transport-Security "max-age=300"

Later:

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

CDN of edge-platform

Als je CDN responseheaders instelt, beheer HSTS dan bij voorkeur op één plek. Stel niet één beleid in bij de origin en een ander aan de edge, tenzij je daar een heel duidelijke reden voor hebt.

Controleer ook of het CDN headers toepast op redirects, gecachete fouten en aangepaste foutpagina’s. Een productiesite is niet alleen zijn 200 OK-response.

HSTS veilig terugdraaien

Als je HSTS moet uitschakelen, stuur dan:

Strict-Transport-Security: max-age=0

Maar er zit een addertje onder het gras: de browser moet de site succesvol via geldige HTTPS kunnen bereiken om die header te ontvangen. Als HTTPS zelf kapot is, kunnen gebruikers met een HSTS-beleid in de cache de instructie die het zou wissen niet ophalen.

De gebruikelijke herstelvolgorde is dus:

  1. Herstel geldige HTTPS.
  2. Serveer Strict-Transport-Security: max-age=0.
  3. Laat dit lang genoeg staan zodat terugkerende gebruikers het ontvangen.
  4. Verwijder of vervang de header nadat het incident is opgelost.

Als het domein is gepreload, is max-age=0 serveren niet genoeg voor nieuwe browserprofielen. Je moet ook verwijdering uit de preload-lijst aanvragen en wachten tot die wijziging via browserupdates wordt verspreid.

Testchecklist voordat je uitrolt

Gebruik deze checklist voordat je max-age verhoogt of includeSubDomains toevoegt:

  • De canonical HTTPS-URL retourneert een geldig certificaat.
  • HTTP leidt om naar HTTPS.
  • Er is maar één HSTS-header.
  • De header verschijnt op redirects en foutresponses waar dat passend is.
  • Alle publieke subdomeinen hebben geldige HTTPS.
  • Certificaatvernieuwing wordt gemonitord.
  • Geen kritiek intern systeem is afhankelijk van HTTP onder hetzelfde hoofddomein.
  • Preload is expliciet besproken, niet uit gewoonte toegevoegd.

Lighthouse kan in sommige contexten ook ontbrekende of zwakke security headers markeren, maar het zou niet je enige verificatiemethode moeten zijn. Als je het gebruikt als onderdeel van een bredere review, lees de bevindingen dan als signalen in plaats van uitspraken; dezelfde houding geldt wanneer je een Lighthouse-rapport leest zonder in paniek te raken.

<!-- tool-cta:start -->

💡 Probeer dit: Controleer vóór en na elke HSTS-wijziging de Strict-Transport-Security-response met Get Headers om te bevestigen dat max-age, includeSubDomains en preload zijn zoals je verwacht.

<!-- tool-cta:end -->

Het privacyargument voor HSTS

HSTS wordt vaak gepresenteerd als een security header, en dat is het ook. Het heeft ook een privacyvoordeel: het verkleint de kans dat de eerste request van een gebruiker via plain HTTP lekt op een niet-vertrouwd netwerk.

Dat doet ertoe op luchthaven-wifi, hotelnetwerken, zakelijke gastnetwerken en overal waar verkeer van een gebruiker kan worden geobserveerd of aangepast. Een plain HTTP-request kan de hostname, het pad, cookies zonder de Secure-flag en andere requestdetails blootleggen. HTTPS is geen magie, maar het consequent afdwingen ervan verwijdert een hele klasse van vermijdbare lekkage.

De beste HSTS-implementaties zijn oninteressant. Ze worden langzaam uitgerold, worden ondersteund door betrouwbare certificaten en zijn saai genoeg dat niemand ze opmerkt. Dat is precies wat je wilt van een header waarvan de faalmodus dramatisch kan zijn.

Veelgestelde vragen

Wat is een veilige eerste HSTS-header?
Begin met `Strict-Transport-Security: max-age=300`. Dat geeft browsers een beleid van vijf minuten: lang genoeg om gedrag te testen, maar kort genoeg om van de meeste fouten snel te herstellen.
Moet elke site includeSubDomains gebruiken?
Nee. Gebruik `includeSubDomains` alleen wanneer elk subdomein onder het hoofddomein geldige HTTPS ondersteunt en dat zal blijven doen. Eén vergeten legacy-host kan onbereikbaar worden voor gebruikers met het beleid in de cache.
Is HSTS preload nodig?
Niet voor de meeste kleine of middelgrote sites. Preload beschermt het allereerste bezoek, maar is moeilijk terug te draaien en vereist dat de volledige domeinnaamruimte klaar is voor HTTPS. Overweeg het pas na een stabiele HSTS-uitrol.
Kan ik HSTS verwijderen door de header te verwijderen?
De header verwijderen voorkomt dat er nieuwe beleidsregels worden ingesteld, maar wist geen beleidsregels die browsers al in de cache hebben. Om HSTS te wissen, serveer je `Strict-Transport-Security: max-age=0` via geldige HTTPS.
Lost HSTS mixed content op?
Nee. HSTS dwingt de verbinding van de top-level site af naar HTTPS. Onveilige asset-URL’s, embedded content en oude hard-gecodeerde `http://`-verwijzingen moet je nog steeds apart repareren.

Bronnen & verder lezen

  1. MDN Web Docs: Strict-Transport-Security
  2. OWASP HTTP Strict Transport Security Cheat Sheet
  3. HSTS Preload Submission Requirements
  4. RFC 6797: HTTP Strict Transport Security
Over de auteur
The Wux Webtools Team

Laatst bijgewerkt:

Blijf lezen