logo

SQL-injektion

SQL Injection är ett säkerhetsfel i webbapplikationer där angripare infogar skadlig SQL-kod genom användarinmatning. Detta kan ge dem tillgång till databasinnehållet för känsliga dataändringar eller till och med ta kontroll över systemet. Det är viktigt att känna till SQL Injection för att hålla webbapplikationer säkra.

SQL Injection (SQLi) är en säkerhetsrisk som uppstår när en angripare kan manipulera en webbapplikations databasfrågor genom att infoga skadlig SQL-kod i användarinmatningsfält. Dessa injicerade frågor kan manipulera den underliggande databasen för att hämta modifiera eller ta bort känsliga data. I vissa fall kan angripare till och med eskalera privilegier och få full kontroll över databasen eller servern.



sql-injektion' title=

Exempel i verkligheten:

2019 inträffade Capital One-dataintrånget på grund av en felkonfigurerad webbapplikation som gjorde det möjligt för en angripare att utnyttja en SQL-injektionssårbarhet. Detta resulterade i läckage av personuppgifter från över 100 miljoner kunder inklusive namn adresser och kreditvärdighet.

SQL-injektionssäkerhetsnivå

DVWA tillhandahåller fyra säkerhetsnivåer för SQL Injection för att hjälpa elever att se hur olika skydd påverkar attacker:



1. Låg säkerhet

Appen tar din input och lägger den direkt i SQL-frågan utan filtrering.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • Går in ': Bryter frågan och gör att databasen skickar ett fel som visar att den är sårbar.
  • Går in 1' OR '1'='1: Lurar frågan till att alltid vara sann så att alla användare returneras.
  • Går in 1' UNION SELECT user password FROM users--: Går med i en annan fråga för att hämta dolda data som användarnamn och lösenord.

2. Medium säkerhet

Appen tillämpar grundläggande ingångssanering med funktioner somaddslashes()att fly'.

$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';

Hur kan attacken vara:



En enkel'injektionen fungerar inte längre (eftersom den blir').

Men angripare kan fortfarande kringgå genom att använda numerisk injektion (eftersom siffror inte behöver citattecken).
Exempel:

protokoll för datalänkslager
1 OR 1=1

Detta returnerar fortfarande alla poster.

3. Hög säkerhet

Appen använder förberedda uttalanden (parameteriserade frågor) för att säkert hantera användarinmatning.

$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);

Attack:

Försök som' OR 1=1ellerUNION SELECTfungerar inte längre.

Frågan behandlar all indata som data inte som SQL-kod.

Typer av SQL-injektion

Det finns olika typer av SQL-injektion

1. Felbaserad SQL-injektion

Felbaserad SQL-injektion är en typ av in-band SQL-injektion där en angripare avsiktligt får databasen att generera ett felmeddelande. Angriparen analyserar sedan detta felmeddelande för att få värdefull information om databasens struktur som tabellnamn och kolumnnamn som kan användas för att skapa ytterligare mer exakta attacker.

Hur det fungerar

Denna attack riktar sig mot applikationer som avslöjar rådatabasfel istället för att visa allmänna meddelanden. Genom att injicera skadlig indata som bryter SQL-syntaxen utlöser angripare dessa fel och får värdefulla ledtrådar om databasstrukturen.

abc med siffror
  1. Identifiera en sårbar ingång: Angriparen hittar ett inmatningsfält som ett sökfält eller en URL-parameter som direkt interagerar med databasen utan korrekt indatasanering.
  2. Injicera en skadlig nyttolast: Angriparen injicerar en specialtecken (som ett enda citat') eller en funktion som är känd för att orsaka ett databasfel.
  3. Analysera felet: Databasen kan inte behandla den felaktiga frågan returnerar ett detaljerat felmeddelande. Detta meddelande kan avslöja viktig information som:
    • Databassystemet (t.ex. MySQL Oracle SQL Server).
    • Versionen av databasen.
    • Hela SQL-frågan körs.
    • Specifika syntaxfel som kan användas för att förstå tabell- eller kolumnnamn.
  4. Förfina attacken: Med hjälp av informationen som samlats in från felmeddelandet kan angriparen förfina sin nyttolast för att extrahera mer data som användarnamn och lösenord.

Exempel:

Steg 1: Ställ in din miljö

  • Starta DVWA. Den nås vanligtvis genom att navigera till en webbadress somhttp://localhost/dvwai din webbläsare.
fil' loading='lazy' title=
  • Logga in på DVWA med standardinloggningsuppgifterna:admin/password.
fil' loading='lazy' title=
  • Gå till fliken DVWA Security och ställ in säkerhetsnivån till låg. Detta kommer att säkerställa att sårbarheterna är lätta att utnyttja.
fil' loading='lazy' title=

Steg 2: Identifiera sårbarheten

SQL Injection-sidan har en enkel inmatningsruta där du kan ange ett användar-ID. Backend-frågan är troligen något liknandeSELECT * FROM users WHERE id = 'user_input'

  • Ange ett giltigt ID som1i inmatningsrutan och klicka på "Skicka". Du bör se detaljerna för användaren med ID 1.
fil' loading='lazy' title=

SQL-injektionskälla

PHP
 $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?>
  • Försök nu att bryta frågan. Ange ett enda citat'i inmatningsrutan och skicka.
fil' loading='lazy' title=

Frågan blir:

SELECT * FROM users WHERE id = ''';

Här ser databasen ett extra citat och vet inte hur man slutför frågan.

städer i australien

Istället för att visa användarinformationen kommer applikationen att returnera ett SQL-fel (något i stil med "Du har ett fel i din SQL-syntax...")

Detta kallas felbaserad SQL-injektion eftersom:

  • Angriparen skickar ogiltig indata (')
  • Databasen ger ett fel
  • Det felet läcker användbar information om databasen (som typ av DB antal kolumner struktur etc.)

2. Unionsbaserad SQL-injektion

Unionsbaserad SQL Injection är en teknik där angripare använderUNIONoperatör för att kombinera resultaten av två eller fleraSELECTuttalanden till en enda resultatuppsättning. Detta kan tillåta dem att extrahera information från andra tabeller i databasen. DeUNIONoperatör kan endast användas om:

  • Båda frågorna har samma antal kolumner
  • Kolumnerna har liknande datatyper
  • Kolumnerna är i samma ordning

UNION Operatör : DenUNIONoperatorn används för att kombinera resultatuppsättningen av två eller fleraSELECTuttalanden.

  • VarjeSELECTuttalande inomUNIONmåste ha samma antal kolumner
  • Kolumnerna måste ha liknande datatyper
  • Kolumnerna måste vara i samma ordning
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

Exempel:

Steg 1: Först måste vi hitta antalet kolumner i den befintliga tabellen på webbplatsen för att injicera UNION-baserad SQL-injektion:

SQL Injection-sidan har en enkel inmatningsruta där du kan ange ett användar-ID. Backend-frågan är troligen något liknande

 SELECT * FROM users WHERE id = 'user_input'

Försök nu att bryta frågan. Ange ett enda citat'i inmatningsrutan och skicka.

Om applikationen är sårbar får du ett detaljerat felmeddelande. Det kan se ut ungefär så här:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

Steg 2: AnvändUNIONNyckelord för att upptäcka antalet kolumner

Att användaUNIONnyckelord (ett vanligt nästa steg) måste du veta antalet kolumner i den ursprungliga frågan. Du kan ta reda på detta genom att användaORDER BYklausul

namn stad i usa
  • Försök att sortera resultaten efter kolumn
1: 1 ORDER BY 1. 
  • Överlämna. Det borde fungera.
fil' loading='lazy' title=

SQL-injektionskälla

PHP
 if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?>
  • Öka antalet:
 1 ORDER BY 2. 

Överlämna. Det borde fungera.

fil' loading='lazy' title=
  • Fortsätt öka tills du får ett felmeddelande. Till exempel1 ORDER BY 4kan ge dig:Unknown column '4' in 'order clause'
  • Det betyder att frågan har 3 kolumner.

3. Blindbaserad SQL-injektion

Blind SQL-injektion inträffar när angripare inte kan se frågeresultat direkt på webbsidan. Istället härleder de information från subtila förändringar i programmets beteende eller svarstid. Även om den är långsammare och tråkigare än klassisk SQLi kan den vara lika effektiv.

Istället för att få tillbaka data härleder angriparen information genom att observera webbsidans beteende. Detta görs vanligtvis på ett av två sätt:

  1. Boolean-baserad blind SQLi: Angriparen injicerar en SQL-fråga som returnerar en sann eller falsk resultat. Webbapplikationens svar ändras beroende på om frågan är sann eller falsk. Till exempel kan sidan visa ett annat meddelande eller göra en annan layout.
  2. Tidsbaserad blind SQLi: Angriparen injicerar en SQL-fråga som får databasen att utföra en tidskrävande åtgärd (som enSLEEP()funktion) om ett villkor är uppfyllt. Angriparen observerar den tid det tar för sidan att laddas för att avgöra om det injicerade villkoret var sant eller falskt.

Exempel:

Föreställ dig en inloggningssida där du anger ett användarnamn och lösenord. Applikationen konstruerar en SQL-fråga så här:

SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'

En blind SQL-injektion skulle innebära att manipulerauser_inputfältet för att ställa en fråga till databasen.

Istället för att få ett direkt svar kan angriparen försöka något i stil med detta:

user_input = 'admin' AND 1=1; --

Om sidan laddas normalt vet angriparen det1=1är en sann påstående.

user_input = 'admin' AND 1=2; --

Om sidan visar ett fel eller beter sig annorlunda vet angriparen det1=2är en falsk påstående.

fil' loading='lazy' title=

Genom att använda en serie av dessa sanna/falska frågor kan en angripare systematiskt gissa och extrahera information en karaktär i taget. Processen kan automatiseras för att gissa allt från tabellnamn till användarlösenord.

Effekten av SQL Injection Attacks

  • Obehörig åtkomst till känsliga uppgifter : Angripare kan hämta personlig ekonomisk eller konfidentiell information lagrad i databasen.
  • Dataintegritetsproblem : Angripare kan ändra radera eller korrumpera kritisk data som påverkar applikationens funktionalitet.
  • Upptrappning av privilegier : Angripare kan kringgå autentiseringsmekanismer och få administrativa rättigheter.
  • Driftstopp : SQL-injektion kan överbelasta servern och orsaka prestandaförsämring eller systemkraschar.
  • Rykteskada : En framgångsrik attack kan allvarligt skada en organisations rykte, vilket leder till att kunderna tappar förtroende.

Förhindra SQL-injektionsattacker

Det finns flera bästa metoder för att förhindra SQL-injektionsattacker:

1. Använd förberedda uttalanden och parametriserade frågor

Förberedda satser och parametriserade frågor säkerställer att användarinmatningar behandlas som data snarare än som en del av SQL-frågan. Detta tillvägagångssätt eliminerar risken för SQL-injektion.

romersk siffra 1 till 100

Exempel i PHP (med MySQLi):

$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();

2. Använd lagrade procedurer

Lagrade procedurer är fördefinierade SQL-frågor lagrade i databasen. Dessa procedurer kan hjälpa till att förhindra SQL-injektion eftersom de inte konstruerar SQL-frågor dynamiskt.

Exempel:

CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;

3. Vitlista Indatavalidering

Se till att användarinmatningar är validerade innan de används i SQL-frågor. Tillåt endast vissa tecken och mönster som alfanumerisk inmatning för fält som användarnamn eller e-postadresser.

4. Använd ORM Frameworks

Object-Relational Mapping (ORM) ramverk som Övervintra eller Entity Framework kan hjälpa till att förhindra SQL-injektion genom att automatiskt hantera frågegenerering och förhindra dynamisk frågekonstruktion.

5. Begränsa databasrättigheter

Ge användarna minsta nödvändiga databasbehörighet. Se till att applikationer endast kan utföra nödvändiga åtgärder (t.ex. VÄLJ INSERT) och begränsa behörigheter som DROP TABLE eller ALTER.

6. Felhantering

Konfigurera databasen och applikationen för att inte visa detaljerade felmeddelanden för användaren. Logga istället fel internt och visa allmänna felmeddelanden till slutanvändare.