Säkerhet i dagens informationssamhälle är mycket mer än brandväggar, lösenord och kryptering av data. En grundläggande princip är att låta säkerhetsarbetet genomsyra hela applikationen och att bygga in säkerhet på alla nivåer i systemet. Det gamla ordspråket om att “kedjan inte är starkare än sin svagaste länk” passar därför inte särskilt väl när det kommer till IT-säkerhet. Här gäller det snarare att ha så många kedjor att det inte gör något om en kedja brister. Förr eller senare kommer det nämligen att hända och är då hela ditt systems säkerhet uppbyggt kring just denna säkerhetsmekanism så är du illa ute.

Ett något banalt exempel, lyckas en obehörig komma över dina loggar är det självklart inget vidare. Har du tänkt till vad det gäller loggnivåer och vilken data som loggas så är det dock förmodligen ingen större fara. Om du däremot rutinmässigt loggar känslig information som personnummer, kontokortsnummer, medicinsk data eller ip-adress till databasservern växer genast problemet lavinartat. Arbetar du dessutom inom en större organisation så kommer du förmodligen att få jobba helg samtidigt som chefen övervakar dig och sakta skruvar upp värmen på blåslampan i takt med att kvällspressen överträffar varandra i smaskiga rubriksättningar.

I mina ögon finns det en miniminivå som alla utvecklare bör känna till och rätta sig efter då detta med säkerhet självklart även gäller applikationerna och den bakomliggande programkoden. Fördelat på två artiklar går jag igenom ett antal grundläggande punkter för säkerhetstänk vid programmering och utveckling.

Vi ger oss därmed raskt in i de vanligaste, och många gånger allvarligaste formerna av attacker som kan avhjälpas rent programmatiskt. Nämligen olika typer av injektioner.

Vad är då en injektionsattack?

Generellt handlar det om att data med ursprung utanför ditt system, exempelvis något som en användare knappar in i ett inmatningsfält, skickas in i ditt system för att utföra uppgifter som inte var avsett. Den mest kända formen av injektion är sannolikt SQL-injektion vilket handlar om att manipulera SQL-frågor mot databasen. Ett exempel på detta kan vara en fråga som kontrollerar om en användares lösenord är korrekt:

I Java skulle detta kunna skrivas:

Ponera sedan att <USERNAME> och <PASSWORD> hämtas från två inmatningsrutor i din applikation. Om en illvillig användare, vi kan kalla honom Bobby, då knappar in ” ’OR ’1’=’1’ ” i lösenordsfältet kommer SQL-frågan som körs mot databasen bli följande:

Eftersom ’1’ = ’1’alltid kommer vara sant så ger denna fråga ett korrekt svar och användaren blir därmed inloggad. Detta utan att Bobby behövde ange vare sig korrekt användarnamn eller lösenord.

Ett mindre känt, men i princip lika allvarligt, exempel är injektioner som riktar in sig mot operativsystemet. Tanken med nedanstående kod är att användaren ska skicka in sökvägen till en katalog och få innehållet listat (i Windowsmiljö).

Antag att vår vän Bobby denna gång skickar in ”dir1 & rd dir2 /S /Q” som argument till ”dir”. Detta gör då att programmet först listar allt i katalogen dir1 och därefter raderar hela dir2 inklusive filer och underkataloger. Återigen kommer du att få ställa in det planerade biobesöket och istället spendera fredagkvällen på kontoret.

Hur kan du då skydda dig?

Det absolut bästa sättet att förebygga olika typer av injektioner är att ta kontroll över användarens input och sanera det från oönskat data. I många fall finns det också färdiga API:er som löser detta åt oss. Javas PreparedStatement som används för att förhindra SQL-injektioner är ett sådant exempel. Koden ovan med inloggningen skulle då kunna skrivas på följande sätt:

 

PreparedStatement sköter här all sanering och det enda du behöver göra som utvecklare är att skicka in användarnamn och lösenord som parametrar. I andra fall där det kanske inte finns färdiga lösningar går det att med relativt enkla medel skydda sig ändå. Är det exempelvis ett inmatningsfält där belopp ska anges så kan alla tecken som inte är numeriska betraktas som ogiltiga:

Hur är det då med output?

Om steg ett mot att säkra din applikation är att ta kontrollen över input så är steg två definitivt att göra motsvarande med det data som skickas ut från din applikation. Detta gäller speciellt om den på något sätt publicerar icke betrodd data, exempelvis via ett forum eller i en kommentarsfunktion. Vissa typer av injektioner, exempelvis Cross Site Scripting (XSS), kan till stor del härröras till just dålig kontroll över systemets output. I XSS-fallet handlar det om att injicera exempelvis javascript på en webbsida i hopp om att skripten ska köras när andra användare går in på sidan.

Precis som med SQL-injektioner så kommer man även här långt med att sanera data i de fall där man inte har kontroll över källan. Detta görs främst genom att “escapa” och “encoda” datat, antingen manuellt eller genom färdiga bibliotek från exempelvis OWASP.

Sammanfattning

För att uppnå en acceptabel nivå av säkerhet krävs det att vi som utvecklare har en medvetenhet om vikten av att sanera såväl indata som utdata när vi skriver vår kod. Att kunskapen om injektioner finns hos Bobby och hans vänner råder det ingen tvekan om. Vid riksdagsvalet 2010 gick det till och med så långt att någon försökte sig på en injektionsattack via röstsedeln och lade sin röst på partiet “DROP TABLE VAL”. Nu ska väl detta snarast ses som humor och inte som en seriös attack men hot som detta är ändå något som vi som utvecklare måste anpassa oss efter.

Injektioner är dock inte det enda vi utvecklare bör ha i bakhuvudet när det kommer till säker utveckling och i del 2 kommer vi därför att gå vidare genom att diskutera ett antal vanliga kodmisstag och hur man lättast kan undvika dessa.

Missa inte senaste blogginläggen – Ta del av vårt nyhetsbrev!