CSRF-beskyttelse og forebyggelse af manipulation med formularer

Forstå CSRF-angreb, og hvordan formulartokens stopper angribere i at overtage dine formularer. Se, hvorfor alle formularer skal have CSRF-beskyttelse.

Kladde

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:

  1. 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.
  2. Gem tokenet på serveren. Gem det knyttet til brugerens session.
  3. Læg tokenet i formularen. Tilføj det som et skjult felt i HTML eller som et meta-tag, JavaScript kan læse.
  4. Tjek ved indsendelse. Før du behandler formulardata, skal du tjekke, at det sendte token passer til det gemte token for sessionen.
  5. 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.

Ofte stillede spørgsmål

Kan en angriber gætte et CSRF-token?
I teorien nej. CSRF-tokens er kryptografisk tilfældige og skifter ofte. En angriber, der prøver at gætte et token, skulle prøve milliarder af muligheder. I praksis er CSRF-tokens så uforudsigelige, at det ikke er et brugbart angreb at gætte. Tokenets styrke kommer af tilfældighed og unikhed, ikke af at holde det hemmeligt.
Hvad sker der, hvis en besøgende sender en formular med et ugyldigt token?
Indsendelsen bliver afvist. Din server behandler ikke formulardataene og gemmer ikke indsendelsen. Den besøgende ser som regel en fejlbesked (for eksempel "Sessionen er udløbet" eller "Ugyldig anmodning") og bliver bedt om at prøve igen. Set fra angriberens side virker den skjulte formular simpelthen ikke.
Skal jeg have CSRF-beskyttelse, hvis min formular ikke kræver login?
Ja. CSRF-angreb kan også virke på formularer, der ikke kræver login. En angriber kan bruge CSRF til at narre en besøgende til at sende uønskede data til en hvilken som helst formular, uanset om den besøgende er logget ind. Hver formular, der behandler indsendelser, skal have CSRF-beskyttelse.
Hvordan adskiller CSRF sig fra XSS?
Cross-Site Scripting (XSS) er, når en angriber lægger ondsindet kode ind på din hjemmeside, som kører i de besøgendes browsere. CSRF er, når en angriber narrer en besøgendes browser til at sende en formular til en anden side. Det er to forskellige angreb med hvert sit forsvar. CSRF-tokens beskytter mod CSRF, mens kontrol og rensning af input beskytter mod XSS.
Hvad med angreb på mobilapps? Virker CSRF-tokens dér?
Mobilapps er mindre udsat for almindelige CSRF-angreb, fordi de ikke automatisk vedhæfter cookies, sådan som browsere gør. Mobilapps bør dog stadig bruge godkendelse med tokens eller certifikater. Bruger en mobilapp cookies eller tokens, der sendes automatisk med anmodninger, bør den også tjekke CSRF-tokens som et ekstra lag beskyttelse.

Brug det med det samme
på din egen hjemmeside.

Start gratis med WEMASY, og byg din side på få minutter.