Lesson 12

Injections och parameteriserade queries

2

Injections

En ny användare vill vara med i vårt nätverk. Denna användare vill ha användarnamnet supertroll','tricked@gmail.com'); DROP TABLE users; --. Vi ska inte döma folks val av namn, så vi kör in den nya användaren i vår databas med email = troll1337@fake.com och age = NULL.

Så vi skriver Pythonkod som konstruerar vår query. Vi använder oss av format string, som skapar en ny sträng genom att stoppa in vardera argument mellan måsvingarna {} i mallen. Till sist kör vi vår query.

Vad händer när vi kör programmet? Jo, alla våra användare raderas. Ifall någon vet strukturen på vårat program så kan de utnyttja det för att interagera med vår databas hur de vill. Hur då? Vi börjar med att titta på vad vår query faktiskt resulterade i.

Det som hände var att de lyckades injicera deras egna SQL kod mellan våran kod. Detta är varför det kallas injections. För att skydda sig emot detta använder vi oss av parametriserade queries.

Varning: skapa aldrig queries genom att manipulera strängar! Använd alltid parametriserade queries!

Parametriserade queries

Med hjälp av vår cursorinstans kan vi enkelt använda oss av parametriserade queries. Vad det betyder är att vi, istället för att konstruera queryn genom manipulera strängar, skickar vår query och argumenten till cursorn och låter den ta hand om att sätta in parameterna på rätt sätt.

I psycopg2 har vi två sätt att nämna var parametrarna ska in i vår query. Vi kan ersätta våra parametrar med %s, ge vår cursor en lista med våra variabler och så kommer de sättas in i ordning.

Eller så kan vi använda oss av namn. Vi ersätter våra parametrar med %(name)s och sedan ger vår cursor en dictionary. Då spelar inte positionen någon roll.

Fixa vår funktion

I förra kapitlet struntade vi att använda oss av parametern number i funktionen get_newest_tweets(number) då vi inte visste om parametriserade queries. Nu kan vi fixa den.

Tweeter/app/database_exercise.py

På startsidan kommer nu färre tweets att visas.

Hashade och saltade lösenord

Eftersom vi redan är på ämnet säkerhet kan det vara ett bra tillfälle att lägga till en tabell med lösenord för alla användare. En tabell med lösenord kommer då att innehålla tuples med en användare från tabellen users och ett lösenord den användaren har (som inte får vara NULL).

Om ni har kört Tweeter/setup.py är denna tabell redan skapad!

Ett problem att spara lösenord är att alla som har tillgång till databasen lätt kan se vilket lösenord varje användare har. Detta är ett enormt säkerhetsproblem! Därför sparar lyckligtvis inte företag lösenord rätt av, utan de hashar och saltar dem.

Att hasha och salta är ett sätt att konvertera ett lösenord genom en systematisk process så att det går att återställa lösenordet (genom den omvända processen) men inte att gissa sig till eller på något sätt skriva ett program som kan lista ut lösenordet (inom rimlig tidsram). För oss är denna process enkel tack vare biblioteket passlib (som installeras om ni kör Tweeter/setup.py), som gör detta åt oss.

Följande är ett exempel på hur vi saltar och hashar ett lösenord:

Koden kommer skriva ut något som är rena rappakaljan! Dock är det bara rappakalja för den som inte vet processen bakom saltningen och hashningen (vilket vi inte vet, vilket är bra för då kan vi inte lista ut lösenorden från rå data heller). Nedan visas ett enkelt program för att skapa ett lösenord och sedan "logga in".

Varning: spara aldrig råa lösenord! Salta och hasha dem innan de sparas någonstans!

Exercise

Det är två saker man alltid måste tänka på när man arbetar med databaser i applikationer för att:

  1. Undvika SQL-injections.

  2. Hålla användares lösenord hemliga.

Vilka är dem?

Solution

  1. Använda parametriserade queries.

  2. Lösenorden ska alltid vara saltade och hashade.

Exercise

Vad kommer hända i följande exempel om användaren 87 har angett följande sträng som sitt lösenord: '0000'; -- '

Solution

Alla användares lösenord kommer att sättas till 0000.

Exercise

Hur bör koden på föregående fråga vara skriven?

Solution

Comments

Martin Lindberg

AAH, särskrivning! cursorinstans är ett ord ;_;

Ted Klein Bergman

Oh noes! D: Nu är det fixat! ^^