SQL-Injection

SQL-Injection är ett mycket vanligt säkerhetsproblem som är värt att skriva om många gånger. Problemet med sql-injection är att det möjliggör för en hackare att bryta sig in i system och/eller förstöra. Ofta används det för att hämta information, exempelvis e-postadresser som senare kan säljas eller användas direkt för att skicka ut spam.

Vi kan tänka oss att följande sträng finns i koden på en sida. Notera hur variablerna username och password konkateneras in i strängen.
select * from users where username='” & username & ”‘ and password=’ ” & password & ”‘

Om vi då tänker oss att en hackare vet att en användare har användarnamnet John, men inte vet lösenordet kan hackaren mata in följande värden:

username = ”John”
password = ”‘ or ‘1’=’1”

Detta kommer innebära att hackaren blir inloggad som John eftersom frågan uppfylls om ‘1’=’1′ vilket alltid är sant.

Den slutgiltiga sql-satsen blir alltså
select * from users where username=’John’ and password = ” or ‘1’1=’1′

Vi kan även tänka oss en fråga såhär:
delete from users where userID=” & id & ”

Vi förväntar oss att användaren är snäll och matar in ett tal så att variabeln id blir ett tal. Men om en elak hacker matar in texten userID, så blir frågan

delete from users where userID=userID
vilket skulle resultera att hela users-tabellen töms.

Det är vanligt förekommande att ta hand om enkelfnuttar, genom att ersätta enkelfnutt till två enkelfnuttar. Exempelvis replace(str, ”‘”, ”””). Detta är dock inte tillräckligt.
Om en användare exempelvis registrerar en användare med namnet admin’– och lösenord password så kommer vi få följande insert till databasen:
”insert into users values(222, ‘admin”–‘, ‘password’)”
Detta ser ju helt korrekt ut. Men om vi sedan tänker oss att man har en funktion där vi kan byta lösenord som de ber oss mata in användarnamn, nuvarande lösenord samt nytt lösenord. I exemplet byter vi från lösenordet password till 123.

update users set password = ‘123’ where username = ‘admin’–‘

Genom att vi registrerade en användare med namnet ”admin’–” vilket i sig är helt rätt kan det bli väldigt fel när vi använder det i andra sammanhang. I ovanstående fall byter vi lösenord på användaren admin till 123.

Det finns fler sätt att jobba med sql-injection. Exempelvis finns det på många sajter någon form av sökfunktion. Om det är en användarbaserad sajt kan vi tänka oss att url:en kan se ut på följande sätt för sökfuntkionen.

http://www.example.com/search/member.aspx?username=john

Ovanstående url kan i slutändan resultera i en sida som listar alla användare som börjar på john och därmed en sql-fråga som ser ut något i stil med.

select username, city from users where username like ‘” & username & ”‘

Det är enkelt att missbruka detta, exempelvis kan vi göra en union och sedan ställa vår egen fråga, men då hämtar vi ut e-post eller lösenord istället för city. Det finns i princip två saker en hackare behöver veta för att kunna utnyttja denna typ av säkerhetshål. Dels namnet på tabellen med informationen till e-post eller lösenordet, samt antal kolumner från den riktiga frågan. I vårt exempel hämtas endast två kolumner. Om systemet är riktigt hjälpsamt så skrivs ett felmeddelande ut, i likhet med:

The Microsoft Jet database engine cannot find the input table or query ‘anvandare’. Make sure it exists and that its name is spelled correctly.

Här ser vi tydligt att tabellen anvandare inte finns och vi provar därför med ett annat tabellnamn.

The number of columns in the two selected tables or queries of a union query do not match.

Nu ser vi att vi har rätt tabellnamn, men att fel antal kolumner är angivna.

Exempel på hur man kan förändra url:en för att hämta ut information om en viss användare kan då se ut såhär:

http://www.example.com/search/member.aspx?username=john’ union select username, password from users

Vi kommer då att få fram en lista på alla användare som heter john men utöver det så kommer alla användare och deras lösenord att visas.

För att skydda sig mot sql-injection finns det flera metoder, ofta vill man jobba med flera skydd.
En bra metod är att använda lagrade procedurer och kontot som webbsidan använder sig av ges rättigheter endast för att köra lagrade procedurer. Kontot får alltså inte läsa/skriva direkt mot tabellerna.
Vill man inte jobba med lagrade procedurer så kan man använda parameteriserade frågor.
Utöver det bör man se till att variablerna endast innehåller den information som förväntas. Om max antal tecken på en användarnamnssökning är 20, så skall man bara kunna skicka in 20 tecken. Det skall vara både klientvalidering och servervalidering. Rätt datatyper skall också valideras. Vi kan tänka oss en querystring där man skall mata in siffor (exempelvis ålder).

2 kommentarer

  1. […] som vi kanske senare skall skicka vidare till databasen eller liknande, vilket minskar risken för sql-injection, xss och andra angrepp på […]

  2. […] artikeln om sql-injection pratades det om vad sql-injection är samt ett antal tänkbara scenarion för vad som kan hända om […]

RSS feed for comments on this post

Kommentarer inaktiverade.

%d bloggare gillar detta: