logo

SQL-injektion

SQL Injection er en sikkerhedsfejl i webapplikationer, hvor angribere indsætter skadelig SQL-kode gennem brugerinput. Dette kan give dem adgang til følsomme dataændringsdatabaseindhold eller endda tage kontrol over systemet. Det er vigtigt at kende til SQL Injection for at holde webapplikationer sikre.

SQL Injection (SQLi) er en sikkerhedssårbarhed, der opstår, når en hacker kan manipulere en webapplikations databaseforespørgsler ved at indsætte ondsindet SQL-kode i brugerindtastningsfelter. Disse indsprøjtede forespørgsler kan manipulere den underliggende database til at hente modificere eller slette følsomme data. I nogle tilfælde kan angribere endda eskalere privilegier og få fuld kontrol over databasen eller serveren.



sql-injektion' title=

Eksempel fra den virkelige verden:

I 2019 opstod Capital One-databruddet på grund af en forkert konfigureret webapplikation, der gjorde det muligt for en angriber at udnytte en SQL-injektionssårbarhed. Dette resulterede i læk af personlige data fra over 100 millioner kunder, herunder navne adresser og kreditvurderinger.

SQL Injection Security Level

DVWA tilbyder fire sikkerhedsniveauer for SQL Injection for at hjælpe eleverne med at se, hvordan forskellige beskyttelser påvirker angreb:



1. Lav sikkerhed

Appen tager dit input og sætter det direkte ind i SQL-forespørgslen uden filtrering.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • Indtastning ': Bryder forespørgslen og får databasen til at smide en fejl, der afslører, at den er sårbar.
  • Indtastning 1' OR '1'='1: Tricker forespørgslen til altid at være sand, så alle brugere returneres.
  • Indtastning 1' UNION SELECT user password FROM users--: Deltager i en anden forespørgsel for at hente skjulte data som brugernavne og adgangskoder.

2. Middel sikkerhed

Appen anvender grundlæggende input-sanering ved hjælp af funktioner somaddslashes()at undslippe'.

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

Hvordan kan angribes:



En simpel'injektion virker ikke længere (fordi den bliver').

Men angribere kan stadig omgå ved hjælp af numerisk indsprøjtning (da tal ikke behøver anførselstegn).
Eksempel:

hvordan man konverterer heltal til streng java
1 OR 1=1

Dette returnerer stadig alle poster.

3. Høj sikkerhed

Appen bruger forberedte udsagn (parameteriserede forespørgsler) til sikkert at håndtere brugerinput.

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

Angreb:

Forsøg som' OR 1=1ellerUNION SELECTikke længere virker.

Forespørgslen behandler alle input som data, ikke SQL-kode.

Typer af SQL-injektion

Der er forskellige typer af SQL Injection

1. Fejlbaseret SQL-injektion

Fejlbaseret SQL-injektion er en type in-band SQL-injektion, hvor en angriber med vilje får databasen til at generere en fejlmeddelelse. Angriberen analyserer derefter denne fejlmeddelelse for at få værdifuld information om databasens struktur som tabelnavne og kolonnenavne, som kan bruges til at lave yderligere mere præcise angreb.

Hvordan det virker

Dette angreb retter sig mod programmer, der afslører rå databasefejl i stedet for at vise generiske meddelelser. Ved at injicere ondsindet input, der bryder SQL-syntaksen, udløser angribere disse fejl og får værdifulde spor om databasestrukturen.

sammenligne i java
  1. Identificer et sårbart input: Angriberen finder et inputfelt som en søgelinje eller en URL-parameter, der interagerer direkte med databasen uden korrekt input-sanering.
  2. Injicer en ondsindet nyttelast: Angriberen injicerer en speciel karakter (som et enkelt citat') eller en funktion, der vides at forårsage en databasefejl.
  3. Analyser fejlen: Databasen ude af stand til at behandle den forkerte forespørgsel returnerer en detaljeret fejlmeddelelse. Denne besked kan afsløre vigtige oplysninger såsom:
    • Databasesystemet (f.eks. MySQL Oracle SQL Server).
    • Versionen af ​​databasen.
    • Den fulde SQL-forespørgsel udføres.
    • Specifikke syntaksfejl, der kan bruges til at forstå tabel- eller kolonnenavne.
  4. Forfin angrebet: Ved at bruge oplysningerne indsamlet fra fejlmeddelelsen kan angriberen forfine deres nyttelast for at udtrække flere data såsom brugernavne og adgangskoder.

Eksempel:

Trin 1: Konfigurer dit miljø

  • Start DVWA. Den tilgås typisk ved at navigere til en URL som f.ekshttp://localhost/dvwai din browser.
fil' loading='lazy' title=
  • Log ind på DVWA med standardoplysningerne:admin/password.
fil' loading='lazy' title=
  • Gå til fanen DVWA Security og indstil sikkerhedsniveauet til lavt. Dette vil sikre, at sårbarhederne er nemme at udnytte.
fil' loading='lazy' title=

Trin 2: Identificer sårbarheden

SQL Injection-siden har en simpel inputboks, hvor du kan indtaste et bruger-id. Backend-forespørgslen er sandsynligvis noget lignendeSELECT * FROM users WHERE id = 'user_input'

  • Indtast et gyldigt ID som1ind i indtastningsfeltet og klik på 'Send'. Du bør se detaljerne for brugeren med ID 1.
fil' loading='lazy' title=

SQL-injektionskilde

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 ?>
  • Prøv nu at bryde forespørgslen. Indtast et enkelt citat'i indtastningsfeltet og indsend.
fil' loading='lazy' title=

Forespørgslen bliver:

SELECT * FROM users WHERE id = ''';

Her ser databasen et ekstra tilbud og ved ikke, hvordan forespørgslen skal udføres.

java lang til streng

I stedet for at vise dig brugeroplysningerne vil applikationen returnere en SQL-fejl (noget som 'Du har en fejl i din SQL-syntaks...')

Dette kaldes fejlbaseret SQL-injektion, fordi:

  • Angriberen sender ugyldigt input (')
  • Databasen giver en fejl
  • Denne fejl lækker nyttig information om databasen (som type DB antal kolonners struktur osv.)

2. Unionsbaseret SQL-injektion

Union-baseret SQL Injection er en teknik, hvor angribere brugerUNIONoperatør for at kombinere resultaterne af to eller flereSELECTudsagn i et enkelt resultatsæt. Dette kan give dem mulighed for at udtrække information fra andre tabeller i databasen. DeUNIONoperatør kan kun bruges hvis:

  • Begge forespørgsler har det samme antal kolonner
  • Kolonnerne har lignende datatyper
  • Kolonnerne er i samme rækkefølge

UNION operatør : DenUNIONoperator bruges til at kombinere resultatsættet af to eller flereSELECTudsagn.

  • hverSELECTerklæring indenforUNIONskal have samme antal kolonner
  • Kolonnerne skal have lignende datatyper
  • Kolonnerne skal være i samme rækkefølge
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

Eksempel:

Trin 1: For det første skal vi finde antallet af kolonner i den eksisterende tabel på webstedet for at injicere UNION-baseret SQL-injektion:

SQL Injection-siden har en simpel inputboks, hvor du kan indtaste et bruger-id. Backend-forespørgslen er sandsynligvis noget lignende

 SELECT * FROM users WHERE id = 'user_input'

Prøv nu at bryde forespørgslen. Indtast et enkelt citat'i indtastningsfeltet og indsend.

Hvis applikationen er sårbar, får du en detaljeret fejlmeddelelse. Det kan se sådan ud:

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

Trin 2: BrugUNIONNøgleord til at opdage antallet af kolonner

For at brugeUNIONsøgeord (et almindeligt næste trin), skal du kende antallet af kolonner i den oprindelige forespørgsel. Du kan finde ud af dette ved at brugeORDER BYklausul

navn by i usa
  • Prøv at sortere resultaterne efter kolonne
1: 1 ORDER BY 1. 
  • Indsend. Det burde virke.
fil' loading='lazy' title=

SQL-injektionskilde

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; } } ?>
  • Øg antallet:
 1 ORDER BY 2. 

Indsend. Det burde virke.

fil' loading='lazy' title=
  • Fortsæt med at stige, indtil du får en fejl. F.eks1 ORDER BY 4kan give dig:Unknown column '4' in 'order clause'
  • Det betyder, at forespørgslen har 3 kolonner.

3. Blind-baseret SQL-injektion

Blind SQL-injektion opstår, når angribere ikke kan se forespørgselsresultater direkte på websiden. I stedet udleder de information fra subtile ændringer i applikationens adfærd eller responstid. Selvom det er langsommere og mere kedeligt end klassisk SQLi, kan det være lige så effektivt.

I stedet for at få data tilbage, udleder angriberen information ved at observere websidens adfærd. Dette gøres typisk på en af ​​to måder:

  1. Boolean-baseret blind SQLi: Angriberen injicerer en SQL-forespørgsel, der returnerer en ægte eller falsk resultat. Webapplikationens svar ændres baseret på, om forespørgslen er sand eller falsk. For eksempel kan siden vise en anden besked eller gengive et andet layout.
  2. Tidsbaseret blind SQLi: Angriberen injicerer en SQL-forespørgsel, der får databasen til at udføre en tidskrævende handling (som fSLEEP()funktion), hvis en betingelse er opfyldt. Angriberen observerer den tid, det tager for siden at indlæse, for at afgøre, om den injicerede tilstand var sand eller falsk.

Eksempel:

Forestil dig en login-side, hvor du indtaster et brugernavn og en adgangskode. Applikationen konstruerer en SQL-forespørgsel som denne:

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

En blind SQL-injektion ville involvere at manipulereuser_inputfelt for at stille databasen et spørgsmål.

I stedet for at få et direkte svar kan angriberen prøve noget som dette:

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

Hvis siden indlæses normalt, ved angriberen det1=1er en ægte erklæring.

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

Hvis siden viser en fejl eller opfører sig anderledes, ved angriberen det1=2er en falsk erklæring.

fil' loading='lazy' title=

Ved at bruge en række af disse sande/falske spørgsmål kan en angriber systematisk gætte og udtrække information én karakter ad gangen. Processen kan automatiseres til at gætte alt fra tabelnavne til brugeradgangskoder.

Virkningen af ​​SQL-injektionsangreb

  • Uautoriseret adgang til følsomme data : Angribere kan hente personlige økonomiske eller fortrolige oplysninger gemt i databasen.
  • Problemer med dataintegritet : Angribere kan ændre slette eller ødelægge kritiske data, der påvirker applikationens funktionalitet.
  • Privilegium eskalering : Angribere kan omgå godkendelsesmekanismer og få administrative rettigheder.
  • Service nedetid : SQL-injektion kan overbelaste serveren, hvilket forårsager ydeevneforringelse eller systemnedbrud.
  • Skade på omdømme : Et vellykket angreb kan alvorligt skade en organisations omdømme, hvilket fører til tab af kundetillid.

Forebyggelse af SQL-injektionsangreb

Der er flere bedste fremgangsmåder til at forhindre SQL-injektionsangreb:

1. Brug forberedte udsagn og parametriserede forespørgsler

Forberedte sætninger og parametriserede forespørgsler sikrer, at brugerinput behandles som data snarere end en del af SQL-forespørgslen. Denne tilgang eliminerer risikoen for SQL-injektion.

Eksempel i PHP (ved hjælp af MySQLi):

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

2. Anvend lagrede procedurer

Lagrede procedurer er foruddefinerede SQL-forespørgsler, der er gemt i databasen. Disse procedurer kan hjælpe med at forhindre SQL-injektion, fordi de ikke dynamisk konstruerer SQL-forespørgsler.

Eksempel:

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

3. Hvidliste Input Validering

Sørg for, at brugerinput er valideret, før de bruges i SQL-forespørgsler. Tillad kun bestemte tegn og mønstre, såsom alfanumerisk input for felter som brugernavne eller e-mailadresser.

4. Brug ORM Frameworks

Object-Relational Mapping (ORM) rammer som Gå i dvale eller Entitetsramme kan hjælpe med at forhindre SQL-injektion ved automatisk at håndtere forespørgselsgenerering og forhindre dynamisk forespørgselskonstruktion.

5. Begræns databaserettigheder

Giv brugere de mindst nødvendige databasetilladelser. Sørg for, at applikationer kun kan udføre nødvendige handlinger (f.eks. SELECT INSERT) og begrænse tilladelser som DROP TABLE eller ALTER.

6. Fejlhåndtering

Konfigurer databasen og applikationen til ikke at vise detaljerede fejlmeddelelser til brugeren. Log i stedet fejl internt og vis generiske fejlmeddelelser til slutbrugere.