0%

Hoofdstuk 10

HTTPS, certificaten en beveiligingsheaders

Wat een certificaat bewijst

Tel de plekken waar deze cursus “alleen via HTTPS” zei. De draagt Secure, dus een browser stuurt hem via HTTPS en nergens anders. Zijn naam begint met __Host-, en zo’n cookie accepteert een browser alleen uit een HTTPS-antwoord. Basic-inloggegevens zijn het wachtwoord in . Een bearer-token werkt voor wie het ook maar in handen heeft. Elk hiervan is alleen veilig als niemand tussen de client en de server het verzoek kan lezen, en alleen als de server aan de andere kant de juiste is.

with Python liet zien dat HTTPS HTTP binnen is, en dat een standaard TLS-context het van de server en zijn naam controleert. Deze les vraagt waaruit die controle bestaat. Waar kijkt een client naar voordat hij een wachtwoord verstuurt?

Een naam, een sleutel, een uitgever en twee datums

Een server die TLS spreekt, laat een certificaat zien. Hier zijn vijf regels van het testcertificaat dat dit hoofdstuk gebruikt, zoals het hulpprogramma openssl ze afdrukt:

Issuer: O=Python Land course tests, CN=TEST ONLY Python Land Web Security course authority
Not Before: Nov  1 00:00:00 2026 GMT
Not After : Nov  1 00:00:00 2046 GMT
Subject: O=Python Land course tests, CN=TEST ONLY reading
DNS:reading.example, DNS:app.reading.example, DNS:notes.reading.example, DNS:localhost, IP Address:127.0.0.1

De laatste regel noemt de namen waarvoor het certificaat geldt. Het bestand bevat ook een publieke sleutel, die hier niet getoond wordt. Een certificaat verbindt dus vier dingen: een naam, een publieke sleutel, een uitgever die de verklaring heeft ondertekend, en de periode waarin die geldt. Dit testbestand geldt twintig jaar. Een certificaat van een publieke uitgever gaat ongeveer een jaar mee, of korter.

Een certificaat is openbaar. De server stuurt het naar elke client die verbinding maakt, en iedereen kan het kopiëren. Wat een bedrieger mist, is de privésleutel die bij de publieke sleutel in het bestand hoort. Tijdens de TLS-handshake bewijst de server dat hij die privésleutel heeft, zonder hem prijs te geven. Een gekopieerd certificaat zonder de sleutel bewijst niets.

Wat verbindt een certificaat?

Ondertekend door iemand die je al vertrouwt

Iedereen kan een bestand schrijven waarin staat “deze sleutel hoort bij reading.example”. Een certificaat telt omdat een uitgever het heeft ondertekend. Een uitgever heet ook wel een certificaatautoriteit (certificate authority); deze les zegt uitgever.

In hoofdstuk 2 beschermde je een bericht met een -tag. Eén sleutel maakte de tag, en dezelfde sleutel controleerde hem. Dat werkt als de twee kanten dezelfde partij zijn, of een geheim delen. Hier kan het niet werken. Elke client ter wereld moet een certificaat kunnen controleren, en wie een HMAC-tag kan controleren, kan er ook een maken.

De handtekening van een uitgever is een ander soort handtekening, een handtekening met een publieke sleutel. De uitgever ondertekent met een privésleutel die hij nooit deelt. Iedereen kan de handtekening controleren met de publieke sleutel van de uitgever, en controleren geeft geen macht om te ondertekenen. Deze cursus bouwt zulke handtekeningen niet; het is genoeg om te weten welke eigenschap ze hebben die een tag met een sleutel mist.

Blijft er één vraag over: waar haalt de client de publieke sleutel van de uitgever vandaan? Hij begint met een van uitgevers die hij vertrouwt, meegeïnstalleerd met het of de browser. De controle eindigt bij die lijst. Een certificaat van een uitgever die er niet op staat, bewijst niets voor deze client, hoe correct het er ook uitziet.

Waarom beschermt een uitgever een certificaat niet met een HMAC-tag, zoals die je in hoofdstuk 2 maakte?

Drie controles

Voordat een client ook maar één byte van een verzoek verstuurt, doet hij drie controles op het certificaat:

  1. Uitgever. Is het ondertekend door een uitgever op mijn lijst?

  2. Naam. Is het voor de naam waar ik om vroeg?

  3. Datum. Valt vandaag binnen de periode?

Hier is een model van de drie controles. Het is een model: een echte client controleert handtekeningen waar deze code namen vergelijkt. Datums in de vorm jaar, maand, dag vergelijken als tekst correct, dus het model bewaart ze als . Voer het uit:

Try it

De eerste drie aanroepen drukken accepted, refused: wrong name en refused: unknown issuer af. Elke weigering noemt één controle. De naamcontrole is degene die mensen vergeten: een vertrouwde uitgever ondertekent certificaten voor miljoenen sites, dus “ondertekend door een vertrouwde uitgever” zegt niets zolang de naam niet ook klopt.

Je maakt verbinding met reading.example. De server laat een certificaat zien dat een uitgever die je vertrouwt voor other.example heeft gemaakt, vandaag geldig. Welke controle faalt?

Wat drukt de vierde aanroep in het blok hierboven af?

Wat een certificaat niet zegt

Een geldig certificaat vertelt je dat je praat met een server die de sleutel heeft voor de naam waar je om vroeg, en dat een uitgever die je vertrouwt dat heeft bevestigd. Verder vertelt het je niets. Het zegt niet wie de site runt, wat de site met een wachtwoord doet, of zijn code veilig is. Bij het gewone soort certificaat controleert een uitgever dat de aanvrager de naam beheert, en meer controleert hij niet. Sommige certificaten noemen ook een organisatie. Daar kijkt een client niet naar: hij controleert de naam. Een site die wachtwoorden als platte tekst opslaat, kan een volkomen geldig certificaat hebben.

Nog één grens, alleen om te herkennen. Een uitgever kan een certificaat vóór de einddatum intrekken; dat heet revocatie (revocation). De standaardcontext van Python controleert daar niet op.

Een site laat een geldig certificaat zien voor de naam die je typte. Wat weet je?

Je kunt nu zeggen wat een client controleert. Niets in je project doet die controles al. De volgende les bouwt het dat het wel doet.