Forestil dig, at nogen narrer en besøgende til at klikke på et link, mens vedkommende er logget ind i sin netbank. Linket fører til en skjult formular, som uden at den besøgende ved det, sender en anmodning til banken om at overføre penge. Banken ser en lovlig anmodning fra en logget ind bruger og udfører den. Angriberen har nu flyttet penge fra offerets konto uden nogensinde at kende adgangskoden.
Det er, hvad CSRF (Cross-Site Request Forgery) er: et angreb, hvor en angriber narrer et offer til uden at vide det at sende en formular eller anmodning til en anden hjemmeside, hvor offeret allerede er logget ind.
Det lærer du: Hvad CSRF-angreb er, og hvordan de virker, hvorfor de er så farlige, selv når andre sikkerhedstiltag er på plads, hvordan CSRF-tokens forhindrer dem, og hvordan du beskytter dine formularer.
Hvad er CSRF?
CSRF (udtales "sea-surf") står for Cross-Site Request Forgery. Det er et angreb, hvor en angriber udnytter, at hvis du er logget ind på en hjemmeside, stoler din browser automatisk på din session og sender den med i hver anmodning til siden, selv når anmodningen kommer fra en anden hjemmeside.
Angrebet virker ved at narre en logget ind besøgende til uden at vide det at sende en formular til en hjemmeside, hvor vedkommende har en konto. Angriberen kan ikke se offerets adgangskode. Det behøver vedkommende heller ikke. Angriberen skal bare have offeret til at være logget ind og så narre det til at sende en anmodning (for eksempel en skjult formular), der gør det, angriberen vil have.
CSRF adskiller sig fra andre angreb, fordi det ikke kræver, at man stjæler loginoplysninger eller bryder kryptering. Det udnytter offerets tillid til hjemmesiden. Offeret er allerede logget ind, så hjemmesiden stoler på anmodninger, der ser ud til at komme fra det.
Sådan virker CSRF-angreb
Et CSRF-angreb sker i tre trin.
Trin 1: Offeret er logget ind på din hjemmeside
Nogen besøger din hjemmeside og logger ind på sin konto. Browseren har nu en aktiv sessionscookie, der beviser, at personen er logget ind. Sessionen er aktiv, så længe personen bruger siden.
Trin 2: Angriberen får offeret til at besøge en ondsindet side
Mens offeret stadig er logget ind på din hjemmeside, besøger vedkommende en side, som angriberen styrer (måske et link fra sociale medier, en vildledende annonce eller en hjemmeside, der ser troværdig ud). På siden ligger skjult kode, der sender en formular tilbage til din hjemmeside.
Trin 3: Formularen sendes automatisk med offerets session
Den skjulte formular sendes til din hjemmeside. Fordi offeret allerede er logget ind, sender browseren automatisk sessionscookien med. Set fra din formulars side er det en lovlig anmodning fra en logget ind bruger. Formularen behandler den, som om offeret selv havde sendt den.
Angriberen har nu gjort noget på din hjemmeside med offerets konto uden at offeret ved det. Det kan være at ændre adgangskoden, overføre penge, opdatere profilen eller sende data.
Hvorfor det virker, selv med andre sikkerhedstiltag
CSRF-angreb går uden om flere almindelige sikkerhedsfunktioner:
HTTPS stopper ikke CSRF. Dataene er krypteret undervejs, men angriberen behøver ikke opfange dem. Vedkommende sender bare anmodningen fra offerets browser, som offerets browser allerede stoler på.
Beskyttelse med adgangskode stopper ikke CSRF. Angriberen har aldrig brug for offerets adgangskode. Vedkommende udnytter bare, at offeret allerede er logget ind.
Et stærkt loginsystem stopper ikke CSRF. Selv hvis godkendelsen er perfekt, virker angrebet, så længe offeret er logget ind.
Derfor er CSRF-beskyttelse et lag for sig. Andre sikkerhedstiltag forhindrer det ikke. Du skal bygge formularerne specifikt, så de kan modstå CSRF-angreb.
CSRF-tokens: sådan stopper de angrebet
Løsningen er et CSRF-token. Det er en unik tekststreng, der ikke kan gættes, og som din server laver til hver formular. Sådan virker det:
Din server laver et unikt token til hver besøgende
Når nogen åbner en side med en formular, laver din server et tilfældigt token og knytter det til brugerens session. Tokenet er forskelligt hver gang, og det er unikt for netop den bruger.
Tokenet ligger i formularen
Tokenet er med som et skjult felt i HTML-formularen. Når den besøgende sender formularen, følger tokenet med.
Din server tjekker tokenet, før den behandler indsendelsen
Når formularen sendes, tjekker din server, om tokenet i indsendelsen er det samme som det, du lavede til denne brugers session. Hvis ja, bliver formularen behandlet. Hvis nej (eller hvis der slet ikke er noget token), bliver formularen afvist.
Angriberens skjulte formular kan ikke indeholde et gyldigt token, fordi tokens ikke kan gættes og er unikke for hver session. En angriber på et andet domæne kan hverken se eller gætte tokenet. Angrebet fejler altså. Den skjulte formular bliver sendt, men din server afviser den, fordi tokenet ikke passer.
Sådan ser et CSRF-token ud i praksis
I HTML ser en formular med CSRF-beskyttelse sådan ud:
<form method="POST" action="/submit-form"> <input type="hidden" name="csrf_token" value="a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"> <input type="email" name="email" placeholder="Din e-mail"> <button type="submit">Send</button> </form> Feltet `csrf_token` er skjult. Den besøgende ser det ikke, men det bliver sendt med formulardataene. Din server tjekker det, før den behandler e-mailen eller andre data.
CSRF-beskyttelse til forskellige typer formularer
Almindelige HTML-formularer
Almindelige HTML-formularer (dem, der sender data til din server med POST) skal have CSRF-tokens. Det gælder kontaktformularer, loginformularer, formularer til nulstilling af adgangskode og alle formularer, der ændrer data på din server.
AJAX- og JavaScript-formularer
Formularer, der sendes med JavaScript til et API-endpoint, skal også have CSRF-beskyttelse. Tokenet kan ligge i selve formularen, være gemt i en cookie eller hentes fra et meta-tag, før anmodningen sendes.
API-anmodninger uden session
Bruger dit API token-baseret godkendelse (som JWT), virker CSRF-beskyttelse anderledes. Browseren kan ikke automatisk vedhæfte et JWT-token, sådan som den vedhæfter en sessionscookie, så almindeligt CSRF er en mindre trussel. Det er dog stadig god praksis at tilføje et ekstra CSRF-token for ekstra beskyttelse.
Andre beskyttelser, der virker sammen med CSRF-tokens
CSRF-tokens er det primære forsvar, men de virker bedst sammen med andre sikkerhedsmetoder.
SameSite-cookies
Når du sætter en sessionscookie, kan du tilføje en `SameSite`-egenskab, der fortæller browseren, at cookien ikke skal sendes med, når anmodningen kommer fra et andet domæne. Så kan angriberens skjulte formular slet ikke bruge offerets session.
Tjek af Referer-headeren
Din server kan tjekke Referer-headeren for at se, hvor anmodningen kom fra. Hvis en indsendelse hævder at komme fra dit domæne, men Referer viser et andet domæne, er det sandsynligvis et angreb. (Referer-headere kan dog forfalskes, så det er ikke et fuldt forsvar.)
Double-submit-cookie-metoden
Her gemmes CSRF-tokenet både i en cookie og i et formularfelt. Din server tjekker, at de passer sammen, før den behandler indsendelsen. Det er mindre almindeligt end almindelige tokens, men virker godt til systemer uden sessioner.
Sådan indfører du CSRF-beskyttelse
Detaljerne afhænger af din teknik, men mønsteret er det samme:
- Lav et unikt token pr. session. Når en bruger starter en session eller åbner en side med en formular, laver din backend et nyt token.
- Gem tokenet på serveren. Gem det knyttet til brugerens session.
- Læg tokenet i formularen. Tilføj det som et skjult felt i HTML eller som et meta-tag, JavaScript kan læse.
- Tjek ved indsendelse. Før du behandler formulardata, skal du tjekke, at det sendte token passer til det gemte token for sessionen.
- Lav et nyt token efter følsomme handlinger. Når en bruger har ændret sin adgangskode eller gjort noget kritisk, laver du et nyt token.
De fleste moderne rammeværker laver og tjekker CSRF-tokens automatisk. Bruger du et rammeværk, er CSRF-beskyttelse som regel slået til som standard. Sørg bare for, at du ikke kommer til at slå det fra.
Almindelige fejl, der gør formularer sårbare
At slå CSRF-beskyttelse fra for nemheds skyld. Nogle udviklere slår CSRF-tjek fra for at gøre test af API'et lettere eller koden enklere. Lad være. Det skaber en reel sårbarhed.
At bruge ét fast token til alle brugere. Tokenet skal være unikt for hver brugers session. Et token, der er det samme for alle (eller det samme alle dage), beskytter ikke mod CSRF.
At lade være med at lave nye tokens. Bruger du det samme token i ugevis, har en angriber mere tid til at udnytte det. Lav nye tokens jævnligt, og altid efter følsomme handlinger.
At stole alene på SameSite-cookies. SameSite hjælper, men er ikke nok. Brug CSRF-tokens som dit primære forsvar og SameSite som reserve.
At glemme tokens på nogle formularer. Beskytter du nogle formularer med tokens, men ikke andre, vil angribere bruge de ubeskyttede. Hver formular, der ændrer data, skal have beskyttelse.
Det gør WEMASY for CSRF-beskyttelse
WEMASY's formularer har automatisk CSRF-token-beskyttelse på hver formular, du laver. Du behøver ikke sætte det op eller tænke over det. Når en besøgende sender en formular, tjekker WEMASY tokenet, før indsendelsen bliver gemt. Beskyttelsen er indbygget og slået til som standard.
Læs mere om muligheder for formularsikkerhed på siden Priser.