HSTS
en webbläsares löfte att använda HTTPS nästa gång
Vad det är
HSTS, utskrivet HTTP Strict Transport Security, är ett svarshuvud som säger åt en webbläsare att
under ett angivet antal sekunder bara nå en webbplats över HTTPS, och att vägra anslutningen helt
när certifikatet är fel. Huvudet heter Strict-Transport-Security, och RFC 6797 har definierat det
sedan november 2012. HSTS krypterar ingenting självt. Det ändrar vad en webbläsare är beredd att
göra över HTTPS.
Ett typiskt värde innehåller två direktiv:
Strict-Transport-Security: max-age=31536000; includeSubDomains
max-age anger hur länge webbläsaren behåller regeln, här ett år. Med includeSubDomains når
regeln varje namn under värdnamnet, så att api.example.com och old.example.com ärver det som
example.com bad om. Ett tredje ord, preload, förekommer i många konfigurationer. Det kommer
från preload-listan på hstspreload.org och inte från RFC:n, och det är webbplatsens samtycke till
att få sitt namn inbyggt i webbläsarna.
När en webbläsare har sett huvudet på ett säkert svar gör den tre saker för det värdnamnet tills
tiden har gått ut. Den skriver om varje http://-adress till https:// innan en begäran lämnar
datorn. Den behandlar varje certifikatfel som ett definitivt stopp, utan någon knapp för att gå
vidare ändå. Och den startar om klockan varje gång huvudet kommer på nytt. Ett svar med
max-age=0 får den att glömma värdnamnet.
Den vanliga jämförelsen är en omdirigering från port 80 till port 443. En omdirigering fungerar,
men först efter att webbläsaren har skickat sin första begäran i klartext, och vem som helst i
samma nätverk kan själv svara på den begäran och hålla kvar besökaren på en okrypterad kopia av
webbplatsen. HSTS tar bort klartextbegäran från varje besök efter det första. Den andra grannen är
Upgrade Insecure Requests, ett direktiv i Content Security Policy. Det uppgraderar de begäranden
som en sida själv gör efter sina skript och bilder, och lämnar en besökare som kommer via någon
annans http://-länk åt omdirigeringen.
Varför det spelar roll
Att slå på HSTS kostar en rad konfiguration. Det verkliga beslutet är hur långt du ska driva det, eftersom varje steg skyddar fler besökare och är svårare att ta tillbaka.
Huvudet ensamt lämnar en lucka som RFC 6797 själv pekar ut. En webbläsare som aldrig har sett
webbplatsen, eller vars sparade policy har löpt ut, börjar fortfarande med en begäran i klartext.
Ett långt max-age krymper den andra halvan av luckan, och därför är ett år den vanliga
inställningen. Den första halvan stängs bara genom preload-listan: värdnamn som kompileras in i
Chrome, medan Firefox, Safari och Edge har egna listor som bygger på den, så att en webbläsare som
just har installerats redan vet att den ska använda HTTPS.
Listan kräver mycket. Basdomänen behöver ett giltigt certifikat, en omdirigering från HTTP till
HTTPS på samma värdnamn, HTTPS på varje underdomän och ett huvud med ett max-age på minst
31 536 000 sekunder, includeSubDomains och preload. Underhållarna säger rakt ut att kravet även
gäller interna underdomäner som allmänheten aldrig ser. Det som avgör frågan är vägen ut: en
borttagning tar månader att nå användarna genom uppdateringar av Chrome, de andra webbläsarna
lämnar inga garantier, och webbplatsen själv beskriver borttagningen som långsam och smärtsam.
Valet går alltså uppför en stege, ett steg i taget:
- Huvudet utan
includeSubDomainspassar nästan varje webbplats som redan levererar HTTPS. RFC 9325, den nuvarande bästa praxisen för TLS, säger att webbservrar bör skicka det. - Att lägga till
includeSubDomainsär säkert först när någon har listat varje namn under domänen och bekräftat att vart och ett svarar på HTTPS, även de som en leverantör eller en annan avdelning driver. - Preload passar en domän vars ägare är säkra på att inget namn under den någonsin behöver klartext-HTTP igen: en inloggningsdomän, en betaldomän, ett företag som styr hela sin egen DNS. En marknadsföringsdomän där ett kampanjverktyg snart kan be om en CNAME-post är en dålig kandidat, och detsamma gäller varje domän som delas med kontorsutrustning.
Listans underhållare anger också takten för klättringen: max-age på 300 sekunder, sedan en
vecka, sedan en månad, varje steg med includeSubDomains, och ett stegs hela ålder ska ha löpt ut
innan nästa börjar. En webbläsare behåller det värde den såg senast, så ett misstag på
femminuterssteget kostar fem minuter.
Så ser det ut i praktiken
På en plattform med yrkes- och organisationsdata arbetade företaget som säkerhetsingenjör och
härdade varje lager, och HSTS var ett av dem.
I middlewaren i Next.js, proxy.ts, bär svaret HSTS
tillsammans med en Content Security Policy med en ny nonce för varje begäran och strict-dynamic,
samt SameSite-cookies. Middlewaren körs framför de rutter den matchar, vilket samlar reglerna som
riktar sig till webbläsaren i en enda fil i stället för att sprida dem över sidorna.
Samma arbete visar var HSTS tar slut. Arbetsantagandet var att klienten är fientlig: allt som webbläsaren upprätthåller kan kopplas bort av den som sitter vid webbläsaren. HSTS skyddar en ärlig besökare mot ett fientligt nätverk. Mot en fientlig klient hjälper det ingenting, och därför fortsatte arbetet i lagren under. API:et fick hastighetsbegränsning, CORS, storleksgränser för begäranden, validering av indata innan något nådde databasen och loggning av säkerhetsrelevanta händelser. API:et anslöt till databasen som en roll som bara fick köra applikationens funktioner, och rättigheterna kontrollerades på nytt på servern vid varje begäran, medan spärrarna i frontenden enbart behandlades som användarupplevelse. I den stacken håller HSTS själva trafiken utom räckhåll, och det är det billigaste lagret att lägga till.
Var det går fel
Huvudet står i konfigurationen, och webbläsarna beter sig som om det saknades. Det skickas på
det okrypterade HTTP-svaret, oftast omdirigeringen, eller på ett HTTPS-svar vars certifikat
webbläsaren underkände. RFC 6797 säger åt webbläsare att ignorera det i båda fallen och åt servrar
att helt hålla det borta från okrypterade svar. Ett närliggande misstag skickar example.com
direkt till https://www.example.com med huvudet bara på www, vilket lämnar basdomänen och dess
andra namn oskyddade. Sätt huvudet på varje HTTPS-svar, omdirigeringar inräknade, och kontrollera
båda dörrarna:
curl -sI https://example.com/ | grep -i strict-transport-security
curl -sI http://example.com/ | grep -i strict-transport-security
Den första raden ska skriva ut huvudet. Den andra hör till omdirigeringen, och där ska utskriften vara tom.
En gammal tjänst under domänen slutar laddas för alla som har besökt huvudwebbplatsen.
includeSubDomains på basdomänen täcker varje namn under den: en statussida som en leverantör
driftar, en skrivares administrationssida, ett intranätverktyg som aldrig har haft något
certifikat. De besökarna möts av ett anslutningsfel utan väg förbi, medan kollegor som aldrig har
öppnat huvudwebbplatsen når tjänsten utan problem, så felrapporterna är svåra att återskapa.
Direktivet gick ut innan någon hade gjort listan. Gör den först, ur DNS-zonen och ur loggarna för
Certificate Transparency, som registrerar varje namn som ett publikt certifikat har utfärdats för.
Flytta varje namn till HTTPS eller till en annan domän, och lägg sedan till direktivet med ett
kort max-age.
En varning som personalen brukade klicka sig förbi blir en mur. En testmiljö med ett självsignerat certifikat, en intern certifikatutfärdare som besökarnas bärbara datorer inte litar på, ett certifikat som gick ut under en helg: före HSTS var vart och ett av dem en varningssida med en väg förbi, och efteråt erbjuder webbläsaren ingen. RFC 9325 nämner självsignerade certifikat som ett fall där HSTS kan göra säkerheten sämre. Ge testmiljön ett publikt betrott certifikat eller en domän som policyn inte når, och behandla certifikatförnyelsen som något som numera tar ner webbplatsen när den fallerar, utan att besökaren får något val.
En domän på preload-listan behöver klartext-HTTP tillbaka. En enhet som bara talar HTTP, en
leverantör vars funktion för egen domän serverar sidor utan certifikat, ett förvärv som tar med
egna värdar under namnet. Posten sitter redan inbyggd i webbläsare som har levererats, och servern
kan göra lite åt saken: en begäran om borttagning når användarna först när deras webbläsare
uppdateras. Lägg det nya namnet under en annan domän, och skicka in domänen till preload-listan
först efter en lång period med ett års max-age och includeSubDomains som har passerat utan ett
enda ärende.
Läs mer
- RFC 6797: HTTP Strict Transport Security (HSTS) — huvudet, dess två direktiv och exakt när en webbläsare måste följa det eller ignorera det.
- HSTS Preload List Submission — villkoren för att komma med på listan, den stegvisa utrullning som underhållarna rekommenderar och vad det kostar att lämna den.
- RFC 9325, section 3.2 — den nuvarande bästa praxisen för TLS om HSTS: klienter och servrar måste stödja det, och servrar bör skicka det.
- Upgrade Insecure Requests — W3C-direktivet som uppgraderar en sidas egna begäranden, och hur det delar arbetet med HSTS.