Cookies afschermen: scripts lezen cookies
Je bent ingelogd op je server uit les 1. Het sessie-id in je browser is een lang, willekeurig getal dat niemand raadt. Maar raden hoeft niet als een script het kan lezen, en standaard kan dat.
Bekijk je eigen cookie
- Open
http://127.0.0.1:8000/static/formulier.htmlen open de ontwikkelaarstools. Kijk in het tabblad App (Firefox: Opslag) onder Cookies bijhttp://127.0.0.1:8000. Daar staatsessie_id, met in de kolom HttpOnly niets:
| Naam | Waarde | HttpOnly | SameSite |
|---|---|---|---|
sessie_id | bb4b18ca1efc4877c990fdadd8a6f593 | Lax |
- Typ in de Console
document.cookie. De Console antwoordt met je sessie-id; bij jou is het getal anders:
document.cookie is niet alleen voor jou in de Console. Elk script dat op deze
pagina draait, kan het ook, en daar zit de zwakheid. Staat er ergens een gat
zoals in HTML van een bezoeker, dan draait er misschien een
script van een ander op je pagina, en dat leest je sessie-id net zo makkelijk.
Er gaat iets mis
Een lege tekst
document.cookie geeft '', een lege tekst, terwijl je wel bent ingelogd.
Oorzaak: je hebt de pagina geopend via localhost:8000 in plaats van
127.0.0.1:8000, of andersom. Het is dezelfde server, maar voor de browser zijn
het twee verschillende sites, elk met eigen cookies.
Oplossing: gebruik overal hetzelfde adres. Log in en open de Console op
127.0.0.1:8000.
Meer cookies dan sessie_id
Naast sessie_id staan er andere cookies in het antwoord, zoals naam of
volgorde.
Oorzaak: een cookie hoort bij het adres, niet bij de map. De cookies van
eerdere projecten op 127.0.0.1 staan er dus ook nog.
Oplossing: verwijder ze in het tabblad App, of werk in een privévenster en log daar opnieuw in.
Opdrachten
Opdracht 1: Investigate - Wat kan iemand met het getal?
Kopieer je sessie-id uit de Console, zonder sessie_id= en de aanhalingstekens.
Maak dief.py en zet het getal bij gestolen:
import httpx
gestolen = "bb4b18ca1efc4877c990fdadd8a6f593"
dief = httpx.Client(base_url="http://127.0.0.1:8000", cookies={"sessie_id": gestolen})
print(dief.post("/bericht", data={"bericht": "Dit schreef ik niet"}).json())
for bericht in dief.get("/berichten").json().values():
print(bericht)
Met cookies= krijgt een Client een cookie mee, alsof hij die al had. Draai
het script. Op wiens naam staat het nieuwe bericht?
Antwoord
Op jouw naam. Het script print eerst {'sleutel': 'bericht_…'}, en in de lijst
staat een regel als:
{'naam': 'sara', 'bericht': 'Dit schreef ik niet'}
Het script kende geen naam en geen wachtwoord, alleen het getal. Voor je server
is dat genoeg: hij zoekt het sessie-id op in sessies.db, en vindt daar jouw
naam. Doe dit alleen met je eigen sessie-id, op je eigen server.
Opdracht 2: Predict - Een ander tabblad
Je opent in hetzelfde browservenster een tweede tabblad met
http://127.0.0.1:8000/berichten, en typt daar in de Console
document.cookie.
Vraag: zie je daar ook je sessie-id?
Antwoord
Ja. Een cookie hoort bij de site, niet bij één pagina of tabblad. Met Path=/
geldt hij voor elke pagina op 127.0.0.1:8000, en een script op elk van die
pagina's kan hem lezen.
Door naar les 3: httponly.