Was ist SQL Injection und wie kann dies in PHP-Anwendungen verhindert werden?

Sie denken also, Ihre SQL-Datenbank ist leistungsfähig und vor sofortiger Zerstörung geschützt? Nun, SQL Injection ist anderer Meinung!


Ja, es handelt sich um sofortige Zerstörung, da ich diesen Artikel nicht mit der üblichen lahmen Terminologie “Verschärfung der Sicherheit” und “Verhinderung von böswilligem Zugriff” öffnen möchte. SQL Injection ist ein so alter Trick in diesem Buch, dass jeder, jeder Entwickler, sehr gut darüber Bescheid weiß und genau weiß, wie man ihn verhindert. Abgesehen von dem einen ungeraden Zeitpunkt, an dem sie ausrutschen, und die Ergebnisse können geradezu katastrophal sein.

Wenn Sie bereits wissen, was SQL Injection ist, können Sie mit der zweiten Hälfte des Artikels fortfahren. Aber für diejenigen, die gerade im Bereich der Webentwicklung auftauchen und davon träumen, höhere Rollen zu übernehmen, ist eine Einführung angebracht.

Was ist SQL Injection??

Der Schlüssel zum Verständnis von SQL Injection liegt in seinem Namen: SQL + Injection. Das Wort “Injektion” hat hier keine medizinischen Konnotationen, sondern ist die Verwendung des Verbs “Injektion”. Zusammen vermitteln diese beiden Wörter die Idee, SQL in eine Webanwendung zu integrieren.

SQL in eine Webanwendung einfügen. . . Hmmm . . . Tun wir das nicht trotzdem? Ja, aber wir möchten nicht, dass ein Angreifer unsere Datenbank steuert. Lassen Sie uns das anhand eines Beispiels verstehen.

Angenommen, Sie erstellen eine typische PHP-Website für einen lokalen E-Commerce-Shop. Fügen Sie daher ein Kontaktformular wie das folgende hinzu:

Dein Name

Deine Nachricht

Nehmen wir an, die Datei send_message.php speichert alles in einer Datenbank, damit die Ladenbesitzer später Benutzernachrichten lesen können. Es kann einen Code wie diesen haben:

<?php

$ name = $ _POST [‘name’];
$ message = $ _POST [‘message’];

// Überprüfen Sie, ob dieser Benutzer bereits eine Nachricht hat
mysqli_query ($ conn, "SELECT * aus Nachrichten mit name = $ name");

// Anderer Code hier

Sie versuchen also zunächst festzustellen, ob dieser Benutzer bereits eine ungelesene Nachricht hat. Die Abfrage SELECT * aus Nachrichten mit name = $ name scheint recht einfach zu sein?

FALSCH!

In unserer Unschuld haben wir die Türen für die sofortige Zerstörung unserer Datenbank geöffnet. Dazu muss der Angreifer die folgenden Bedingungen erfüllen:

  • Die Anwendung wird in einer SQL-Datenbank ausgeführt (heute ist fast jede Anwendung)
  • Die aktuelle Datenbankverbindung verfügt über die Berechtigungen “Bearbeiten” und “Löschen” für die Datenbank
  • Die Namen der wichtigen Tabellen können erraten werden

Der dritte Punkt bedeutet, dass Sie jetzt, da der Angreifer weiß, dass Sie einen E-Commerce-Shop betreiben, die Bestelldaten sehr wahrscheinlich in einer Auftragstabelle speichern. Mit all dem bewaffnet, muss der Angreifer lediglich Folgendes als Namen angeben:

Joe; Bestellungen abschneiden;? Jawohl! Mal sehen, wie die Abfrage wird, wenn sie vom PHP-Skript ausgeführt wird:

SELECT * FROM Nachrichten WHERE Name = Joe; Bestellungen abschneiden;

Okay, der erste Teil der Abfrage weist einen Syntaxfehler auf (keine Anführungszeichen um „Joe“), aber das Semikolon zwingt die MySQL-Engine, eine neue zu interpretieren: Befehle abschneiden. Auf diese Weise ist auf einen Schlag die gesamte Bestellhistorie verschwunden!

Nachdem Sie nun wissen, wie SQL Injection funktioniert, müssen Sie sich überlegen, wie Sie es stoppen können. Die beiden Bedingungen, die für eine erfolgreiche SQL-Injection erfüllt sein müssen, sind:

  1. Das PHP-Skript sollte über Änderungs- / Löschrechte für die Datenbank verfügen. Ich denke, dies gilt für alle Anwendungen, und Sie können Ihre Anwendungen nicht schreibgeschützt machen. �� Und raten Sie mal, selbst wenn wir alle Änderungsrechte entfernen, kann SQL Injection es jemandem ermöglichen, SELECT-Abfragen auszuführen und die gesamte Datenbank anzuzeigen, einschließlich vertraulicher Daten. Mit anderen Worten, das Reduzieren der Datenbankzugriffsebene funktioniert nicht und Ihre Anwendung benötigt es trotzdem.
  2. Benutzereingaben werden verarbeitet. Die SQL-Injection kann nur funktionieren, wenn Sie Daten von Benutzern akzeptieren. Auch hier ist es nicht praktisch, alle Eingaben für Ihre Anwendung zu stoppen, nur weil Sie sich Sorgen über die SQL-Injection machen.

Verhindern der SQL-Injection in PHP

Wie können wir nun die SQL-Injection verhindern, da Datenbankverbindungen, Abfragen und Benutzereingaben Teil des Lebens sind? Zum Glück ist es ziemlich einfach und es gibt zwei Möglichkeiten, dies zu tun: 1) Benutzereingaben bereinigen und 2) vorbereitete Anweisungen verwenden.

Benutzereingaben bereinigen

Wenn Sie eine ältere PHP-Version verwenden (5.5 oder niedriger, und dies passiert häufig beim Shared Hosting), ist es ratsam, alle Benutzereingaben über eine Funktion namens mysql_real_escape_string () auszuführen. Grundsätzlich werden dadurch alle Sonderzeichen in einer Zeichenfolge entfernt, sodass sie bei Verwendung durch die Datenbank ihre Bedeutung verlieren.

Wenn Sie beispielsweise eine Zeichenfolge haben, wie ich eine Zeichenfolge bin, kann ein Angreifer das einfache Anführungszeichen (‘) verwenden, um die erstellte Datenbankabfrage zu bearbeiten und eine SQL-Injection zu verursachen. Wenn Sie es durch mysql_real_escape_string () ausführen, wird eine Zeichenfolge erstellt, die dem einfachen Anführungszeichen einen Backslash hinzufügt und ihm entgeht. Infolgedessen wird die gesamte Zeichenfolge jetzt als harmlose Zeichenfolge an die Datenbank übergeben, anstatt an der Abfragemanipulation teilnehmen zu können.

Dieser Ansatz hat einen Nachteil: Es ist eine sehr, sehr alte Technik, die mit den älteren Formen des Datenbankzugriffs in PHP einhergeht. Ab PHP 7 existiert diese Funktion nicht mehr, was uns zu unserer nächsten Lösung bringt.

Verwenden Sie vorbereitete Anweisungen

Mit vorbereiteten Anweisungen können Datenbankabfragen sicherer und zuverlässiger durchgeführt werden. Anstatt die Rohabfrage an die Datenbank zu senden, teilen wir der Datenbank zunächst die Struktur der Abfrage mit, die wir senden möchten. Dies ist es, was wir unter „Vorbereitung“ einer Erklärung verstehen. Sobald eine Anweisung vorbereitet ist, übergeben wir die Informationen als parametrisierte Eingaben, damit die Datenbank die Lücken füllen kann, indem sie die Eingaben in die zuvor gesendete Abfragestruktur einfügt. Dadurch wird den Eingängen möglicherweise jede besondere Leistung entzogen, sodass sie im gesamten Prozess als bloße Variablen (oder Nutzlasten, wenn Sie so wollen) behandelt werden. So sehen vorbereitete Aussagen aus:

<?php
$ servername = "localhost";;
$ username = "Nutzername";;
$ password = "Passwort";;
$ dbname = "myDB";;

// Verbindung herstellen
$ conn = new mysqli ($ Servername, $ Benutzername, $ Passwort, $ Datenbankname);

// Verbindung prüfen
if ($ conn->connect_error) {
sterben("Verbindung fehlgeschlagen: " . $ conn->connect_error);
}}

// vorbereiten und binden
$ stmt = $ conn->bereiten("INSERT INTO MyGuests (Vorname, Nachname, E-Mail) VALUES (?,?,?)");
$ stmt->bind_param ("sss", $ Vorname, $ Nachname, $ E-Mail);

// Parameter setzen und ausführen
$ firstname = "John";;
$ lastname = "Damhirschkuh";;
$ email = "[E-Mail geschützt]";;
$ stmt->ausführen();

$ firstname = "Maria";;
$ lastname = "Moe";;
$ email = "[E-Mail geschützt]";;
$ stmt->ausführen();

$ firstname = "Julie";;
$ lastname = "Dooley";;
$ email = "[E-Mail geschützt]";;
$ stmt->ausführen();

Echo "Neue Datensätze erfolgreich erstellt";;

$ stmt->schließen();
$ conn->schließen();
?>

Ich weiß, dass der Prozess unnötig komplex klingt, wenn Sie mit vorbereiteten Aussagen noch nicht vertraut sind, aber das Konzept ist die Mühe wert. Hier ist eine schöne Einführung.

Für diejenigen, die bereits mit der PDO-Erweiterung von PHP vertraut sind und damit vorbereitete Anweisungen erstellen, habe ich einen kleinen Ratschlag.

Warnung: Seien Sie vorsichtig beim Einrichten des PDO

Wenn wir PDO für den Datenbankzugriff verwenden, können wir in ein falsches Sicherheitsgefühl geraten. “Ah, nun, ich benutze PDO. Jetzt muss ich an nichts anderes mehr denken “- so geht unser Denken im Allgemeinen. Es ist richtig, dass PDO (oder von MySQLi vorbereitete Anweisungen) ausreicht, um alle Arten von SQL-Injection-Angriffen zu verhindern. Sie müssen jedoch beim Einrichten vorsichtig sein. Es ist üblich, nur Code aus Tutorials oder früheren Projekten zu kopieren und einzufügen und fortzufahren. Diese Einstellung kann jedoch alles rückgängig machen:

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, true);

Mit dieser Einstellung wird PDO angewiesen, vorbereitete Anweisungen zu emulieren, anstatt die Funktion für vorbereitete Anweisungen der Datenbank tatsächlich zu verwenden. Folglich sendet PHP einfache Abfragezeichenfolgen an die Datenbank, auch wenn Ihr Code so aussieht, als würde er vorbereitete Anweisungen erstellen und Parameter festlegen. Mit anderen Worten, Sie sind genauso anfällig für SQL-Injection wie zuvor. ��

Die Lösung ist einfach: Stellen Sie sicher, dass diese Emulation auf false gesetzt ist.

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, false);

Jetzt muss das PHP-Skript vorbereitete Anweisungen auf Datenbankebene verwenden, um alle Arten von SQL-Injection zu verhindern.

Verhindern der Verwendung von WAF

Wissen Sie, dass Sie Webanwendungen auch mithilfe der WAF (Webanwendungs-Firewall) vor SQL-Injection schützen können??

Nun, nicht nur SQL Injection, sondern viele andere Layer 7-Schwachstellen wie Cross-Site-Scripting, fehlerhafte Authentifizierung, Cross-Site-Fälschung, Datenexponierung usw. Entweder können Sie selbst gehostete wie Mod Security oder Cloud-basiert wie folgt verwenden.

SQL Injection und moderne PHP Frameworks

Die SQL-Injection ist so verbreitet, so einfach, so frustrierend und so gefährlich, dass alle modernen PHP-Webframeworks mit Gegenmaßnahmen ausgestattet sind. In WordPress haben wir zum Beispiel die $ wpdb->Die Funktion prepare (). Wenn Sie ein MVC-Framework verwenden, erledigt es die ganze Drecksarbeit für Sie und Sie müssen nicht einmal daran denken, die SQL-Injection zu verhindern. Es ist ein wenig ärgerlich, dass Sie in WordPress Anweisungen explizit vorbereiten müssen, aber hey, es ist WordPress, über das wir sprechen. ��

Mein Punkt ist jedenfalls, dass die moderne Generation von Webentwicklern nicht über SQL-Injection nachdenken muss und sich daher der Möglichkeit nicht einmal bewusst ist. Selbst wenn sie eine Hintertür in ihrer Anwendung offen lassen (möglicherweise handelt es sich um einen $ _GET-Abfrageparameter und alte Gewohnheiten, eine schmutzige Abfrage auszulösen), können die Ergebnisse katastrophal sein. Es ist also immer besser, sich die Zeit zu nehmen, um tiefer in die Fundamente einzutauchen.

Fazit

SQL Injection ist ein sehr böser Angriff auf eine Webanwendung, der jedoch leicht vermieden werden kann. Wie wir in diesem Artikel gesehen haben, reicht es aus, bei der Verarbeitung von Benutzereingaben vorsichtig zu sein (übrigens ist SQL Injection nicht die einzige Bedrohung, die die Verarbeitung von Benutzereingaben mit sich bringt) und die Datenbank abzufragen. Wir arbeiten jedoch nicht immer an der Sicherheit eines Webframeworks. Es ist daher besser, sich dieser Art von Angriff bewusst zu sein und nicht darauf hereinzufallen.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map