OWASP Top 10, injeksjon, XSS og inputvalidering.
Aldri stol på brukerinput
Sikker programmering handler om å skrive kode som er motstandsdyktig mot angrep. Mange sikkerhetshull oppstår fordi utviklere stoler for mye på brukerinput eller glemmer grunnleggende tiltak. Det viktigste prinsippet kan derfor oppsummeres i én setning: aldri stol på brukerinput.
All data fra brukere – fra skjemaer, URL-parametere, cookies eller filer – må valideres og saniteres før den brukes. Validering kan skje i tre lag. Klientside-validering med JavaScript gir rask tilbakemelding, men kan enkelt omgås, så du må aldri stole på den alene. Serverside-validering med Python eller Node.js er obligatorisk – den kan ikke omgås av brukeren og er din siste forsvarslinje. Database-validering med constraints og fremmednøkler gir et ekstra lag.
To teknikker er særlig nyttige. Whitelist betyr at du bare tillater spesifikke, kjente verdier – vil du sortere etter et felt, sjekker du at feltet finnes i en liste av gyldige verdier før du bruker det. Type-sjekk betyr å bekrefte at input har riktig datatype, for eksempel at en alder faktisk er et tall. Begge bygger på samme idé: i stedet for å lete etter alt som er farlig, slipper du bare inn det du vet er trygt.
SQL injection og XSS
To av de farligste sårbarhetene fortjener særlig oppmerksomhet. Den første er SQL injection (A03 i OWASP Top 10), som oppstår når en angriper kan injisere SQL-kode gjennom input. Bygger du en spørring med f-strenger, og angriperen skriver ' OR '1'='1, blir spørringen sann for alle rader og returnerer hele tabellen. Med '; DROP TABLE brukere; -- kan angriperen slette tabellen. Løsningen er, som du har lært, parameteriserte spørringer: skriv ? (i SQLite) eller %s (i PostgreSQL) der verdiene skal inn, og la databasebiblioteket sette dem trygt:
cursor.execute("SELECT * FROM brukere WHERE brukernavn = ?", (brukernavn,))Den andre er Cross-Site Scripting (XSS), som oppstår når en angriper kan injisere skadelig JavaScript i en webside som andre brukere ser. Det finnes tre typer: stored XSS, der koden lagres i databasen og vises til alle (som i et kommentarfelt); reflected XSS, der koden sendes som parameter og reflekteres tilbake (som på en søkeside); og DOM-based XSS, der svakheten ligger i klientsidens JavaScript. Skriver en angriper <script>alert(document.cookie)</script> som brukernavn, kjøres scriptet hos alle som ser siden – og kan stjele cookies, omdirigere til phishing eller kjøre keyloggere. Forsvaret er output encoding/escaping: tegn som < gjøres om til ufarlig tekst. Flask sin Jinja2 escaper automatisk, så {{ brukernavn }} er trygt – men du må unngå |safe uten god grunn, fordi det slår av beskyttelsen.
CSRF – når nettleseren blir lurt
Den tredje sårbarheten er mer lumsk. Cross-Site Request Forgery (CSRF, uttales «sea-surf») er et angrep der en ondsinnet side lurer nettleseren din til å sende forespørsler til en annen side der du er innlogget. Tenk deg at du er logget inn på bank.no. Så besøker du ondsinnet.com, som inneholder et skjult bilde:
<img src="https://bank.no/overforing?til=angriper&belop=10000">Nettleseren laster «bildet», og sender automatisk med din innloggede sesjon-cookie til bank.no. Banken ser en gyldig, innlogget forespørsel og utfører overføringen. Det skremmende er at du ikke gjorde noe galt selv – nettleseren ble lurt på dine vegne.
Forsvaret er CSRF-tokens. Idéen er enkel: serveren legger en hemmelig, uforutsigbar verdi inn i hvert skjema, og krever at denne verdien sendes tilbake ved innsending. Den ondsinnede siden kjenner ikke tokenet og kan derfor ikke forfalske en gyldig forespørsel. I Flask gjør biblioteket Flask-WTF dette automatisk: når du bruker en FlaskForm, genereres og valideres CSRF-tokenet for deg. Dette, kombinert med at sensitive handlinger bruker POST i stedet for GET, gjør at angriperens skjulte bilde-triks ikke lenger fungerer. CSRF minner oss om en viktig sannhet: noen ganger er det ikke koden din som angripes direkte, men tilliten mellom nettleseren og serveren.
Oppsummering
Sikker programmering hviler på én gylden regel: aldri stol på brukerinput. All data må valideres, helst med whitelist og type-sjekk, og serverside-validering er obligatorisk siden klientside kan omgås. Vi så de tre store webangrepene og forsvaret mot dem. SQL injection stoppes med parameteriserte spørringer. XSS stoppes med output encoding/escaping, som Jinja2 gjør automatisk så lenge du unngår |safe. Og CSRF stoppes med CSRF-tokens, gjerne via Flask-WTF, og ved å bruke POST for sensitive handlinger.
Fellesnevneren er at angrep ofte utnytter tillit – tillit til input, til innhold, eller mellom nettleser og server. Ved å bygge inn forsvar i hvert lag gjør vi koden motstandsdyktig. I neste kapittel går vi videre til kryptering og autentisering i praksis.
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.