SQL-in­jek­tio­ner utgör ett betydande hot mot re­la­tions­da­ta­bas­mo­del­ler och den känsliga in­for­ma­tion de in­ne­hål­ler. Därför är ett om­fat­tan­de skydd mot dessa obehöriga externa åt­komst­för­sök – som möj­lig­görs av sä­ker­hets­bris­ter – absolut nöd­vän­digt.

Vad är en SQL-injektion?

En SQL-injektion är en typ av attack som utnyttjar en sä­ker­hets­brist i re­la­tions­da­ta­bas­sy­stem som använder SQL-frå­ge­språ­ket för att bearbeta an­vän­da­rin­mat­ning. An­gri­pa­ren utnyttjar an­vän­da­rin­mat­ning­ar som inte är korrekt skyddade och in­ne­hål­ler spe­ci­al­tec­ken som dubbla bin­de­streck, citat­tec­ken eller semikolon. Dessa tecken har spe­ci­al­funk­tio­ner för SQL-tolken och gör det möjligt att ma­ni­pu­le­ra kommandon som exekveras externt. SQL-in­jek­tio­ner är ofta för­knip­pa­de med PHP- och ASP-ap­pli­ka­tio­ner som använder föråld­ra­de gräns­snitt. I många av dessa fall är in­mat­ning­en inte till­räck­ligt ren, vilket gör den till ett primärt mål för en attack.

Genom att stra­te­giskt infoga funk­tions­tec­ken kan en obehörig användare infoga yt­ter­li­ga­re SQL-kommandon och ma­ni­pu­le­ra da­ta­bas­pos­ter för att läsa, ändra eller radera data. I all­var­li­ga fall kan angripare till och med få tillgång till systemets kom­man­do­rad, vilket kan göra det möjligt för dem att ta full kontroll över da­ta­bas­ser­vern.

Exempel på SQL-injektion som visar hur en da­ta­ba­s­at­tack fungerar

Eftersom sårbara da­ta­bas­ser­ve­rar kan iden­ti­fie­ras snabbt och SQL-in­jek­tions­at­tac­ker är relativt enkla att utföra, är denna metod fort­fa­ran­de en av de mest använda tek­ni­ker­na bland cy­ber­brotts­ling­ar världen över. Angripare använder olika stra­te­gi­er och utnyttjar både nyupp­täck­ta och gamla sä­ker­hets­bris­ter i de ap­pli­ka­tio­ner som används i da­ta­han­te­rings­pro­ces­sen. För att bättre förstå hur SQL-injektion fungerar i praktiken, ska vi titta på två vanliga at­tack­me­to­der som exempel.

Exempel 1: Åtkomst via dåligt skyddad an­vän­da­rin­mat­ning

För att få åtkomst till en databas måste an­vän­dar­na van­ligt­vis först au­ten­ti­se­ra sig. För detta ändamål används ofta skript för att visa ett in­logg­nings­for­mu­lär med fält för an­vän­dar­namn och lösenord. An­vän­dar­na fyller i for­mu­lä­ret och skriptet kon­trol­le­rar sedan om det finns matchande poster i databasen. Som standard kan databasen innehålla en tabell med namnet users med ko­lum­ner­na username och password. I en typisk web­bap­pli­ka­tion kan de relevanta skriptra­der­na för da­ta­bas­åt­komst (med Python-liknande pseudokod) se ut så här:

uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)
python

En angripare kan nu ma­ni­pu­le­ra lö­senords­fäl­tet med hjälp av en SQL-injektion, till exempel genom att ange password' OR 1='1, vilket re­sul­te­rar i följande SQL-fråga:

sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"
python

Detta ger an­gri­pa­ren full åtkomst till hela an­vändar­ta­bel­len i databasen, eftersom lö­senords­vill­ko­ret alltid ut­vär­de­ras till sant (1='1'). Om an­gri­pa­ren loggar in som ad­mi­nist­ra­tör kan hen fritt ändra alla da­ta­bas­pos­ter. Al­ter­na­tivt kan an­vän­dar­namns­fäl­tet ma­ni­pu­le­ras på samma sätt.

Exempel 2: Da­taut­vin­ning via ID-ma­ni­pu­la­tion

Att söka in­for­ma­tion från en databas med hjälp av ID är en praktisk och vanlig metod, men öppnar också en möjlig dörr för SQL-injektion. Till exempel vet en webb­ser­ver genom en överförd ID-uppgift i en URL vilken in­for­ma­tion den ska hämta från databasen. Mot­sva­ran­de PHP-skript ser ut så här:

<?php
    $mysqli = new mysqli("localhost", "username", "password", "database");
    $id = intval($_GET['id']);
    $result = $mysqli->query("SELECT * FROM table WHERE id=$id");
    while ($row = $result->fetch_assoc()) {
        echo print_r($row, true);
    }
?>
php

Den för­vän­ta­de URL:en följer mönstret .../script.php?id=22. I detta fall skulle ta­bell­pos­ten med ID:t ”22” hämtas. Om en obehörig person har möjlighet att ma­ni­pu­le­ra denna URL och istället skickar en begäran som .../script.php?id=22+OR+1=1, kommer den re­sul­te­ran­de frågan att leda till att alla rader i tabellen hämtas:

SELECT * FROM table WHERE id=22 OR 1=1;
sql

Hur hittar brotts­ling­ar sårbara da­ta­bas­sy­stem?

I princip kan alla webb­plat­ser eller web­bap­pli­ka­tio­ner som använder SQL-databaser utan för­be­red­da frågor (för­be­red­da ut­ta­lan­den) eller andra skydds­åt­gär­der vara sårbara för SQL-in­jek­tio­ner. Upptäckta sår­bar­he­ter förblir inte dolda länge på internet. Det finns faktiskt webb­plat­ser som pub­li­ce­rar upp­da­te­ra­de listor över kända sä­ker­hets­bris­ter – och till och med förklarar hur angripare kan använda Google-sökningar för att hitta matchande webb­pro­jekt. Om en webbplats re­tur­ne­rar de­tal­je­ra­de SQL-fel­med­de­lan­den kan cy­ber­brotts­ling­ar använda dessa med­de­lan­den för att iden­ti­fi­e­ra po­ten­ti­el­la sår­bar­he­ter. Till exempel kan det räcka med att lägga till en apostrof i slutet av en URL som in­ne­hål­ler en ID-parameter för att avslöja en svaghet, som visas i följande exempel:

[DomainName].com/news.php?id=5’

En sårbar webbplats skickar tillbaka ett fel­med­de­lan­de i följande form:

Query failed: You have an error in your SQL syntax…

Liknande metoder kan också användas för att extrahera antalet kolumner, tabell- och ko­lumn­namn, SQL-versionen eller till och med an­vän­dar­namn och lösenord. Dessutom finns det olika verktyg som kan au­to­ma­ti­se­ra både upp­täckts­pro­ces­sen och ut­fö­ran­det av SQL-in­jek­tions­at­tac­ker.

Hur du skyddar din databas från SQL-injektion

Det finns olika metoder som du kan använda för att förhindra SQL-in­jek­tions­at­tac­ker på ditt da­ta­bas­sy­stem. Du bör hantera alla kom­po­nen­ter som är in­blan­da­de – servern och enskilda ap­pli­ka­tio­ner samt da­ta­bashan­te­rings­sy­ste­met.

Steg 1: Övervaka au­to­ma­ti­se­ra­de in­mat­ning­ar från ap­pli­ka­tio­ner

När man bearbetar indata från externa eller inbäddade ap­pli­ka­tio­ner är det viktigt att validera och filtrera de inlämnade värdena för att förhindra SQL-in­jek­tio­ner.

1. Validera datatyper

Varje inmatning ska matcha den för­vän­ta­de datatypen. Om till exempel en numerisk inmatning krävs kan en enkel va­li­de­ring i PHP se ut så här:

if (filter_var($input, FILTER_VALIDATE_INT) === false) {
    throw new InvalidArgumentException("Invalid input");
}
php

Liknande kon­trol­ler bör ge­nom­fö­ras för strängar, datum eller andra specifika format.

2. Filtrera spe­ci­al­tec­ken

Spe­ci­al­tec­ken kan skapa sä­ker­hets­ris­ker, särskilt i SQL- eller HTML-sam­man­hang. Ett säkert till­vä­ga­gångs­sätt är att använda htmlspecialchars() för HTML-inmatning och PDO::quote() för SQL-frågor.

3. Undvik att visa fel­med­de­lan­den

Direkta fel­med­de­lan­den som avslöjar tekniska detaljer om databasen eller systemet bör undvikas. Visa istället ett generellt med­de­lan­de, till exempel:

echo "An error occurred. Please try again later.";
error_log("Unexpected error encountered. See system log for details.");
php

4. Använd för­be­red­da ut­ta­lan­den

Ett av de mest effektiva sätten att förhindra SQL-in­jek­tio­ner är att använda för­be­red­da satser. I denna metod skickas SQL-kommandon och pa­ra­met­rar separat, så att skadlig kod inte kan köras. Här är ett exempel på im­ple­men­te­ring i PHP med PDO (PHP Data Objects):

$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();
php

Da­ta­bashan­te­rings­sy­ste­met sä­ker­stäl­ler au­to­ma­tiskt att in­mat­ning­en behandlas på ett säkert sätt.

Steg 2: Sä­ker­ställ om­fat­tan­de ser­ver­skydd

Sä­ker­he­ten för den server som ditt da­ta­bashan­te­rings­sy­stem körs på spelar också en avgörande roll för att förhindra SQL-injektion. En viktig åtgärd är att stärka ope­ra­tiv­sy­ste­met genom att följa dessa bästa praxis:

  • In­stal­le­ra eller aktivera endast de program och tjänster som är nöd­vän­di­ga för att köra databasen.
  • Ta bort alla oanvända eller onödiga an­vän­dar­kon­ton.
  • Se till att alla relevanta system- och pro­gram­upp­da­te­ring­ar in­stal­le­ras ome­del­bart.
  • Tillämpa principen om minsta möjliga be­hö­rig­het för att sä­ker­stäl­la att användare och tjänster endast beviljas de minsta nöd­vän­di­ga be­hö­rig­he­ter­na.

Beroende på sä­ker­hets­kra­ven för ditt webb­pro­jekt bör du överväga yt­ter­li­ga­re skydds­åt­gär­der:

  • Intrusion Detection Systems (IDS) och Intrusion Pre­ven­tion Systems (IPS): Dessa system använder olika de­tek­te­rings­me­to­der för att iden­ti­fi­e­ra attacker tidigt, utfärda varningar och – när IPS används – au­to­ma­tiskt initiera mo­tåt­gär­der.
  • Ap­pli­ca­tion Layer Gateway (ALG): En ALG övervakar och filtrerar trafiken mellan ap­pli­ka­tio­ner och webb­lä­sa­re direkt på ap­pli­ka­tions­ni­vå.
  • Web Ap­pli­ca­tion Firewall (WAF): En WAF skyddar specifikt web­bap­pli­ka­tio­ner från SQL-injektion och Cross-Site Scripting (XSS) genom att blockera eller rensa miss­tänk­ta för­fråg­ning­ar.
  • Zero Trust-metod: Denna moderna sä­ker­hets­mo­dell sä­ker­stäl­ler att varje åt­komst­för­sök – oavsett ursprung – ve­ri­fie­ras och au­ten­ti­se­ras innan åtkomst beviljas.
  • Brand­vägg­s­reg­ler och nät­verks­seg­men­te­ring: Dessa är viktiga för att minimera at­tacky­tan på lång sikt.
  • Re­gel­bund­na IT-sä­ker­hets­re­vi­sio­ner och pe­netra­tions­tes­ter: Dessa hjälper till att upptäcka och åtgärda sår­bar­he­ter i ett tidigt skede.

Steg 3: Hårda databasen och använd säker kod

Precis som ditt ope­ra­tiv­sy­stem bör din databas rensas från alla onödiga kom­po­nen­ter och hållas upp­da­te­rad. Ta bort alla lagrade pro­ce­du­rer som du inte behöver och in­ak­ti­ve­ra alla oanvända tjänster och an­vän­dar­kon­ton. Skapa ett dedikerat da­ta­bas­kon­to som endast är avsett för web­båt­komst och tilldela det endast de minsta nöd­vän­di­ga be­hö­rig­he­ter­na.

I linje med an­vänd­ning­en av för­be­red­da ut­ta­lan­den re­kom­men­de­ras det starkt att inte använda mysql PHP-modulen (som togs bort i PHP 7). Välj istället mysqli eller PDO för att sä­ker­stäl­la bättre säkerhet och kom­pa­ti­bi­li­tet. En säker mysqli kan se ut så här:

$mysqli = new mysqli("localhost", "username", "password", "database");
if ($mysqli->connect_error) die("Connection failed");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$stmt->bind_result($hashedPassword);
if ($stmt->fetch() && password_verify($_POST['password'], $hashedPassword)) {
    echo "Login successful";
} else {
    echo "Invalid login credentials";
}
$stmt->close();
$mysqli->close();
php

Lösenord ska aldrig lagras direkt i en databas eller hämtas i klartext. Använd istället en hashmetod som password_hash() i kom­bi­na­tion med password_verify() för att skydda in­logg­nings­upp­gif­ter­na på ett säkert sätt. En säker im­ple­men­te­ring kan se ut så här:

$mysqli = new mysqli("localhost", "username", "password", "database");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if ($row && password_verify($_POST['password'], $row['password'])) {
    echo "Login successful!";
} else {
    echo "Incorrect username or password.";
}
php

Vad har bobby-tabeller med SQL-injektion att göra?

Webb­plat­sen bobby-tables.com använder en xkcd-webb­ko­misk för att på ett hu­mo­ris­tiskt sätt il­lu­stre­ra farorna med osäker an­vän­da­rin­mat­ning i databaser. I komiken får en mamma ett te­le­fon­sam­tal från sin sons (kär­leks­fullt kallad Little Bobby Tables) skola. Den som ringer frågar om hennes son verkligen heter Robert'); DROP TABLE Students;--, vilket hon svarar ja på. An­led­ning­en till samtalet blir snart klar: försöket att lägga in Robert i elev­da­ta­ba­sen ledde till att hela elev­ta­bel­len raderades. Mamman är inte särskilt för­stå­en­de – hon hoppas bara att skolan har lärt sig sin läxa och kommer att rensa databasen framöver.

Serien belyser tydligt de ka­ta­stro­fa­la kon­se­kven­ser som kan uppstå om man inte validerar och sanerar an­vän­da­rin­mat­ning­ar i da­ta­basap­pli­ka­tio­ner på rätt sätt.

Gå till huvudmeny