logo

SQL-Injection

SQL-Injection ist eine Sicherheitslücke in Webanwendungen, bei der Angreifer durch Benutzereingaben schädlichen SQL-Code einfügen. Dies kann es ihnen ermöglichen, auf vertrauliche Daten zuzugreifen, Datenbankinhalte zu ändern oder sogar die Kontrolle über das System zu übernehmen. Es ist wichtig, über SQL-Injection Bescheid zu wissen, um die Sicherheit von Webanwendungen zu gewährleisten.

SQL-Injection (SQLi) ist eine Sicherheitslücke, die auftritt, wenn ein Angreifer die Datenbankabfragen einer Webanwendung manipulieren kann, indem er bösartigen SQL-Code in Benutzereingabefelder einfügt. Diese injizierten Abfragen können die zugrunde liegende Datenbank manipulieren, um vertrauliche Daten abzurufen, zu ändern oder zu löschen. In manchen Fällen können Angreifer sogar ihre Berechtigungen erweitern und so die volle Kontrolle über die Datenbank oder den Server erlangen.



SQL-Injektion' title=

Beispiel aus der Praxis:

Im Jahr 2019 kam es zu einer Datenschutzverletzung bei Capital One aufgrund einer falsch konfigurierten Webanwendung, die es einem Angreifer ermöglichte, eine SQL-Injection-Schwachstelle auszunutzen. Dies führte zum Verlust personenbezogener Daten von über 100 Millionen Kunden, darunter Namen, Adressen und Kreditwürdigkeit.

SQL-Injection-Sicherheitsstufe

DVWA bietet vier Sicherheitsstufen für SQL-Injection, um den Lernenden zu zeigen, wie sich unterschiedliche Schutzmaßnahmen auf Angriffe auswirken:



1. Geringe Sicherheit

Die App nimmt Ihre Eingaben auf und fügt sie ohne Filterung direkt in die SQL-Abfrage ein.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • Eintreten ': Unterbricht die Abfrage und sorgt dafür, dass die Datenbank einen Fehler ausgibt, der angibt, dass sie anfällig ist.
  • Eintreten 1' OR '1'='1: Bringt die Abfrage dazu, immer wahr zu sein, sodass alle Benutzer zurückgegeben werden.
  • Eintreten 1' UNION SELECT user password FROM users--: Verbindet eine andere Abfrage, um versteckte Daten wie Benutzernamen und Passwörter abzurufen.

2. Mittlere Sicherheit

Die App wendet eine grundlegende Eingabebereinigung mit Funktionen wie anaddslashes()entkommen'.

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

Wie kann Angriff erfolgen:



Ein einfaches'Die Injektion funktioniert nicht mehr (weil es so ist).').

Angreifer können dies jedoch immer noch mithilfe der numerischen Injektion umgehen (da Zahlen keine Anführungszeichen benötigen).
Beispiel:

Gimp löscht den Hintergrund
1 OR 1=1

Dadurch werden weiterhin alle Datensätze zurückgegeben.

3. Hohe Sicherheit

Die App verwendet vorbereitete Anweisungen (parametrisierte Abfragen), um Benutzereingaben sicher zu verarbeiten.

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

Angriff:

Versuche wie' OR 1=1oderUNION SELECTnicht mehr funktionieren.

Die Abfrage behandelt alle Eingaben als Daten und nicht als SQL-Code.

Arten der SQL-Injection

Es gibt verschiedene Arten von SQL-Injection

1. Fehlerbasierte SQL-Injection

Fehlerbasierte SQL-Injection ist eine Art In-Band-SQL-Injection, bei der ein Angreifer absichtlich bewirkt, dass die Datenbank eine Fehlermeldung generiert. Anschließend analysiert der Angreifer diese Fehlermeldung, um wertvolle Informationen über die Struktur der Datenbank wie Tabellennamen und Spaltennamen zu erhalten, die für weitere, präzisere Angriffe verwendet werden können.

Wie es funktioniert

Dieser Angriff zielt auf Anwendungen ab, die unformatierte Datenbankfehler aufdecken, anstatt generische Meldungen anzuzeigen. Durch das Einschleusen bösartiger Eingaben, die die SQL-Syntax zerstören, lösen Angreifer diese Fehler aus und gewinnen wertvolle Hinweise auf die Datenbankstruktur.

String-Formatierung Java
  1. Identifizieren Sie eine anfällige Eingabe: Der Angreifer findet ein Eingabefeld wie eine Suchleiste oder einen URL-Parameter, der ohne ordnungsgemäße Eingabebereinigung direkt mit der Datenbank interagiert.
  2. Injizieren Sie eine bösartige Nutzlast: Der Angreifer fügt ein Sonderzeichen (z. B. ein einfaches Anführungszeichen) ein') oder eine Funktion, die bekanntermaßen einen Datenbankfehler verursacht.
  3. Analysieren Sie den Fehler: Die Datenbank kann die fehlerhafte Abfrage nicht verarbeiten und gibt eine detaillierte Fehlermeldung zurück. Diese Nachricht kann wichtige Informationen enthalten, wie zum Beispiel:
    • Das Datenbanksystem (z. B. MySQL Oracle SQL Server).
    • Die Version der Datenbank.
    • Die vollständige SQL-Abfrage wird ausgeführt.
    • Spezifische Syntaxfehler, die zum Verständnis von Tabellen- oder Spaltennamen verwendet werden können.
  4. Verfeinern Sie den Angriff: Anhand der aus der Fehlermeldung gesammelten Informationen kann der Angreifer seine Nutzlast verfeinern, um weitere Daten wie Benutzernamen und Passwörter zu extrahieren.

Beispiel:

Schritt 1: Richten Sie Ihre Umgebung ein

  • Starten Sie DVWA. Der Zugriff erfolgt normalerweise durch Navigieren zu einer URL wiehttp://localhost/dvwain Ihrem Browser.
Datei' loading='lazy' title=
  • Melden Sie sich mit den Standardanmeldeinformationen bei DVWA an:admin/password.
Datei' loading='lazy' title=
  • Gehen Sie zur Registerkarte „DVWA-Sicherheit“ und stellen Sie die Sicherheitsstufe auf „Niedrig“ ein. Dadurch wird sichergestellt, dass die Schwachstellen leicht ausgenutzt werden können.
Datei' loading='lazy' title=

Schritt 2: Identifizieren Sie die Schwachstelle

Die SQL-Injection-Seite verfügt über ein einfaches Eingabefeld, in das Sie eine Benutzer-ID eingeben können. Die Backend-Abfrage ist wahrscheinlich so etwas wieSELECT * FROM users WHERE id = 'user_input'

  • Geben Sie eine gültige ID ein, z1in das Eingabefeld ein und klicken Sie auf „Senden“. Sie sollten die Details für den Benutzer mit der ID 1 sehen.
Datei' loading='lazy' title=

SQL-Injection-Quelle

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 ?>
  • Versuchen Sie nun, die Abfrage zu unterbrechen. Geben Sie ein einfaches Anführungszeichen ein'in das Eingabefeld eintragen und abschicken.
Datei' loading='lazy' title=

Die Abfrage wird zu:

SELECT * FROM users WHERE id = ''';

Hier sieht die Datenbank ein zusätzliches Angebot und weiß nicht, wie sie die Abfrage abschließen soll.

MySQL hat den Beitritt verlassen

Anstatt Ihnen die Benutzerdetails anzuzeigen, gibt die Anwendung einen SQL-Fehler zurück (etwa „Sie haben einen Fehler in Ihrer SQL-Syntax…“).

Dies wird als fehlerbasierte SQL-Injection bezeichnet, weil:

  • Der Angreifer sendet eine ungültige Eingabe (')
  • Die Datenbank gibt einen Fehler aus
  • Durch diesen Fehler werden nützliche Informationen über die Datenbank preisgegeben (z. B. die Art der Datenbank, die Anzahl der Spalten, die Struktur usw.).

2. Union-basierte SQL-Injection

Union-basierte SQL-Injection ist eine Technik, bei der Angreifer die verwendenUNIONOperator, um die Ergebnisse von zwei oder mehr zu kombinierenSELECTAnweisungen in eine einzige Ergebnismenge. Dadurch können sie Informationen aus anderen Tabellen in der Datenbank extrahieren. DerUNIONDer Operator kann nur verwendet werden, wenn:

  • Beide Abfragen haben die gleiche Anzahl an Spalten
  • Die Spalten haben ähnliche Datentypen
  • Die Spalten sind in der gleichen Reihenfolge

UNION-Operator : DerUNIONDer Operator wird verwendet, um die Ergebnismenge von zwei oder mehr zu kombinierenSELECTAussagen.

  • JedeSELECTAussage innerhalbUNIONmüssen die gleiche Anzahl von Spalten haben
  • Die Spalten müssen ähnliche Datentypen haben
  • Die Spalten müssen in der gleichen Reihenfolge sein
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

Beispiel:

Schritt 1: Zuerst müssen wir die Anzahl der Spalten der vorhandenen Tabelle auf der Website ermitteln, um eine UNION-basierte SQL-Injection einzuschleusen:

Die SQL-Injection-Seite verfügt über ein einfaches Eingabefeld, in das Sie eine Benutzer-ID eingeben können. Die Backend-Abfrage ist wahrscheinlich so etwas wie

 SELECT * FROM users WHERE id = 'user_input'

Versuchen Sie nun, die Abfrage zu unterbrechen. Geben Sie ein einfaches Anführungszeichen ein'in das Eingabefeld eintragen und abschicken.

Wenn die Anwendung angreifbar ist, erhalten Sie eine detaillierte Fehlermeldung. Es könnte etwa so aussehen:

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

Schritt 2: Benutzen Sie dieUNIONSchlüsselwort zum Ermitteln der Anzahl der Spalten

Um das zu nutzenUNIONSchlüsselwort (ein üblicher nächster Schritt) müssen Sie die Anzahl der Spalten in der ursprünglichen Abfrage kennen. Das können Sie herausfinden, indem Sie die nutzenORDER BYKlausel

Name Stadt in den USA
  • Versuchen Sie, die Ergebnisse nach Spalten zu sortieren
1: 1 ORDER BY 1. 
  • Einreichen. Es sollte funktionieren.
Datei' loading='lazy' title=

SQL-Injection-Quelle

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; } } ?>
  • Erhöhen Sie die Zahl:
 1 ORDER BY 2. 

Einreichen. Es sollte funktionieren.

Datei' loading='lazy' title=
  • Erhöhen Sie weiter, bis Sie eine Fehlermeldung erhalten. Zum Beispiel1 ORDER BY 4könnte Ihnen Folgendes geben:Unknown column '4' in 'order clause'
  • Das bedeutet, dass die Abfrage drei Spalten hat.

3. Blindbasierte SQL-Injection

Blinde SQL-Injection tritt auf, wenn Angreifer die Abfrageergebnisse nicht direkt auf der Webseite sehen können. Stattdessen leiten sie Informationen aus subtilen Änderungen im Verhalten oder der Reaktionszeit der Anwendung ab. Obwohl es langsamer und mühsamer als klassisches SQLi ist, kann es ebenso effektiv sein.

Anstatt Daten zurückzubekommen, leitet der Angreifer Informationen aus der Beobachtung des Verhaltens der Webseite ab. Dies geschieht normalerweise auf zwei Arten:

  1. Boolescher Blind-SQLi: Der Angreifer fügt eine SQL-Abfrage ein, die a zurückgibt WAHR oder FALSCH Ergebnis. Die Antwort der Webanwendung ändert sich je nachdem, ob die Abfrage wahr oder falsch ist. Die Seite könnte beispielsweise eine andere Nachricht anzeigen oder ein anderes Layout rendern.
  2. Zeitbasiertes Blind-SQLi: Der Angreifer fügt eine SQL-Abfrage ein, die dazu führt, dass die Datenbank eine zeitaufwändige Aktion ausführt (z. B. eineSLEEP()Funktion), wenn eine Bedingung erfüllt ist. Der Angreifer beobachtet die Zeit, die zum Laden der Seite benötigt wird, um festzustellen, ob die eingefügte Bedingung wahr oder falsch war.

Beispiel:

Stellen Sie sich eine Anmeldeseite vor, auf der Sie einen Benutzernamen und ein Passwort eingeben. Die Anwendung erstellt eine SQL-Abfrage wie folgt:

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

Eine blinde SQL-Injection würde eine Manipulation beinhaltenuser_inputFeld, um der Datenbank eine Frage zu stellen.

Anstatt eine direkte Antwort zu erhalten, könnte der Angreifer Folgendes versuchen:

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

Wenn die Seite normal lädt, weiß der Angreifer das1=1ist ein WAHR Stellungnahme.

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

Wenn die Seite einen Fehler anzeigt oder sich anders verhält, weiß der Angreifer das1=2ist ein FALSCH Stellungnahme.

Datei' loading='lazy' title=

Durch die Verwendung einer Reihe dieser Richtig/Falsch-Fragen kann ein Angreifer systematisch Zeichen für Zeichen erraten und Informationen extrahieren. Der Prozess kann automatisiert werden, um alles zu erraten, vom Tabellennamen bis zum Benutzerpasswort.

Post-Order-Traversal

Auswirkungen von SQL-Injection-Angriffen

  • Unbefugter Zugriff auf sensible Daten : Angreifer können in der Datenbank gespeicherte persönliche Finanz- oder vertrauliche Informationen abrufen.
  • Probleme mit der Datenintegrität : Angreifer können kritische Daten ändern, löschen oder beschädigen, was sich auf die Funktionalität der Anwendung auswirkt.
  • Eskalation von Berechtigungen : Angreifer können Authentifizierungsmechanismen umgehen und Administratorrechte erlangen.
  • Ausfallzeit des Dienstes : SQL-Injection kann den Server überlasten und zu Leistungseinbußen oder Systemabstürzen führen.
  • Reputationsschaden : Ein erfolgreicher Angriff kann den Ruf eines Unternehmens ernsthaft schädigen und zu einem Vertrauensverlust der Kunden führen.

Verhindern von SQL-Injection-Angriffen

Es gibt mehrere Best Practices zur Verhinderung von SQL-Injection-Angriffen:

1. Verwenden Sie vorbereitete Anweisungen und parametrisierte Abfragen

Vorbereitete Anweisungen und parametrisierte Abfragen stellen sicher, dass Benutzereingaben als Daten und nicht als Teil der SQL-Abfrage behandelt werden. Dieser Ansatz eliminiert das Risiko einer SQL-Injection.

Beispiel in PHP (mit MySQLi):

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

2. Setzen Sie gespeicherte Prozeduren ein

Gespeicherte Prozeduren sind vordefinierte SQL-Abfragen, die in der Datenbank gespeichert werden. Diese Verfahren können dazu beitragen, SQL-Injection zu verhindern, da sie SQL-Abfragen nicht dynamisch erstellen.

Beispiel:

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

3. Eingabevalidierung auf der Whitelist

Stellen Sie sicher, dass Benutzereingaben validiert werden, bevor sie in SQL-Abfragen verwendet werden. Erlauben Sie nur bestimmte Zeichen und Muster, wie z. B. alphanumerische Eingaben für Felder wie Benutzernamen oder E-Mail-Adressen.

4. Verwenden Sie ORM-Frameworks

Object-Relational Mapping (ORM)-Frameworks wie Überwintern oder Entity-Framework kann dazu beitragen, SQL-Injection zu verhindern, indem die Abfragegenerierung automatisch verarbeitet wird und eine dynamische Abfragekonstruktion verhindert wird.

5. Beschränken Sie die Datenbankrechte

Gewähren Sie Benutzern die mindestens erforderlichen Datenbankberechtigungen. Stellen Sie sicher, dass Anwendungen nur notwendige Aktionen ausführen können (z. B. SELECT INSERT) und beschränken Sie Berechtigungen wie DROP TABLE oder ALTER.

6. Fehlerbehandlung

Konfigurieren Sie die Datenbank und die Anwendung so, dass dem Benutzer keine detaillierten Fehlermeldungen angezeigt werden. Protokollieren Sie stattdessen Fehler intern und zeigen Sie den Endbenutzern generische Fehlermeldungen an.