Schützen Sie Ihre Datenbank vor SQL Injections
SQL-Injections treten auf, wenn ein Angreifer durch böswillige Abfragen unbefugten Zugriff auf eine Datenbank erhält oder sogar Befehle direkt in der Datenbank ausführt. Laut dem Open Web Application Security Project (OWASP) stehen Code-Injektionen ganz oben auf der Liste der größten Sicherheitsrisiken für Webanwendungen. Dies ist sinnvoll, da eine schlecht gestaltete Datenbank es einem böswilligen Angreifer ermöglichen kann, Autorisierungsmechanismen zu umgehen und eine gesamte Datenbank abzurufen oder zu bearbeiten, was eindeutig ein enormes Datenschutz- und Sicherheitsrisiko darstellt. In einigen Fällen erhalten Angreifer sogar eine „Hintertür“ in eine Datenbank, die es ihnen ermöglicht, langfristig auf die Systeme eines Unternehmens zuzugreifen, wenn dies unbemerkt bleibt.
Wie können SQL-Injections passieren?
SQL-Injections können auftreten, wenn eine Anwendung von einem Benutzer eingegebene Daten, z. B. in einem Anmeldeformular, aufnimmt und diese nicht vertrauenswürdigen Daten vor dem Hinzufügen zu einer SQL-Abfrage nicht ordnungsgemäß bereinigt.
Es gibt viele Beispiele dafür, wie sich dies auf ein Unternehmen auswirken kann:
Zugriff auf private Benutzerdaten
Nehmen wir an, wir haben eine Anwendung, in der sich Benutzer mit einem Benutzernamen und einem Kennwort anmelden. Wenn der Benutzer den Benutzernamen "harrypotter" und das Kennwort "hogwarts" angegeben hat, überprüft die SQL-Abfrage normalerweise die Anmeldeinformationen und gibt die Informationen für den Benutzer wie folgt zurück:
SELECT *
FROM users
WHERE username = ‘harrypotter’
AND password = ‘hogwarts’;
Ein böswilliger Benutzer kann eine unsichere Datenbank ausnutzen, indem er die Abfrage so anpasst, dass sie unabhängig von der Eingabe immer true zurückgibt und auf alle Daten zugreift:
SELECT *
FROM users
WHERE username = ‘’ OR 1=1--’;
Wenn der Angreifer ’ OR 1=1--’
als Benutzernamen eingibt, wird die Kennwortanforderung umgangen und alle Benutzerdaten werden zurückgegeben. Dies liegt daran, dass 1 = 1 immer true zurückgibt und das Symbol - häufig verwendet wird, um den Rest einer Abfrage zu "kommentieren", was bedeutet, dass sie nicht erreicht wird.
Anzeigen versteckter Daten
Stellen Sie sich ein Szenario vor, in dem auf einer E-Commerce-Website nur die Elemente angezeigt werden, die bereits auf einer Webseite veröffentlicht wurden. Vielleicht haben sie eine mit Spannung erwartete neue Schuhkollektion, die bald auf der Website verfügbar sein wird, aber noch nicht für die Öffentlichkeit zugänglich ist. Die URL für eine solche Seite könnte ungefähr so aussehen:
https://webstore.com/products?category=shoes
Wenn der Benutzer auf diese URL zugreift, erstellt die Anwendung eine SQL-Abfrage, um alle derzeit verfügbaren Schuhe aus der Datenbank abzurufen:
SELECT *
FROM products
WHERE category = ‘shoes’
AND released = 1;
Diese Abfrage ruft alle Artikel aus der Produkttabelle ab, die sich in der Kategorie Schuhe befinden und freigegeben wurden (released = 1
: Die Artikel aus der neuen Kollektion werden mit released = 0
gekennzeichnet).
Ohne ordnungsgemäße Steuerung könnte ein Angreifer dieses System durch Ändern der URL austricksen:
https://webstore.com/products?category=shoes’--
Die neue Abfrage würde folgendermaßen aussehen:
SELECT *
FROM products
WHERE category = ‘shoes’--’
AND released = 1;
In der obigen Abfrage wird der letzte Teil (AND released = 1
) auskommentiert und daher nie eingeschlossen, sodass alle Produkte zurückgegeben werden. Der Angreifer hat jetzt Zugriff auf alle Informationen über die neue Sammlung und kann diese Informationen an die Öffentlichkeit weitergeben.
Abrufen von Daten aus anderen Tabellen
Ein Angreifer kann nicht nur auf Daten aus einer Tabelle zugreifen, sondern auch das Schlüsselwort UNION verwenden, um Elemente aus einer anderen Tabelle vollständig auszuwählen. Angenommen, ein Angreifer hat auf der Grundlage des obigen Beispiels die folgende URL angegeben:
https://webstore.com/products?category=shoes' UNION SELECT name, address FROM users--
Dies würde die folgende endgültige Abfrage erstellen:
SELECT *
FROM products
WHERE category = ‘shoes’
UNION SELECT name, address
FROM users--
... und dem Angreifer den Zugriff auf private Kundendaten ermöglichen.
Löschen von Informationen
Auf einigen Datenbankservern können mehrere durch Semikolons getrennte SQL-Anweisungen gleichzeitig ausgeführt werden. In unserem laufenden Beispiel kann die URL für Artikel 100 wie folgt geändert werden:
https://webstore.com/items/itemid=100; DROP TABLE users
Dies erstellt folgende Abfrage:
SELECT *
FROM items
WHERE itemid = 100;
DROP TABLE users;
Dadurch werden alle User-Daten gelöscht.
Quelle: xkcd.com/327
Wie können SQL-Injections verhindert werden?
Es ist klar, dass SQL-Injections ein großes Datenschutz- und Sicherheitsrisiko darstellen. Wie können sie also verhindert werden?
In einem ersten Schritt sollten die eingehenden Daten „bereinigt“ werden. Dazu müssen Sie nach speziellen Symbolen, Null / Leer-Eingaben oder allgemeinen SQL-Injection-Anzeichen suchen und diese gegebenenfalls entfernen. Wir möchten auch überprüfen, ob die Daten das richtige Format haben, bevor wir sie zulassen (z. B. sollten Kreditkartennummern den erwarteten Datentyp und die erwartete Länge haben).
Eine weitere wichtige vorbeugende Maßnahme besteht darin, beim Erstellen von Abfragen "parametrisierte Abfragen" anstelle der Verkettung von Zeichenfolgen zu berücksichtigen. In diesem Fall enthält die Abfrage einen Platzhalter, anstatt nur die Benutzereingaben einzufügen. Wenn eine falsche Eingabe übermittelt wird, wird weiterhin ein Fehler generiert, der Angreifer kann jedoch nicht auf die Datenbank zugreifen.
Ein einfaches Beispiel man den ursprünglichen Code, der die Verkettung von Zeichenfolgen verwendete, anpassen kann:
“SELECT *
FROM users
WHERE username =
‘“ + username + “’
AND password =
‘“ + password * “‘
Um in etwa wie folgt auszusehen:
sql = “SELECT *
FROM users
WHERE username = '%s’
AND password = '%s’”
args = (my_username, my_password)
cursor.execute(sql, args)
In diesem Fall kann die Abfrage keine neue Abfrage dynamisch erstellen, wenn schädlicher Text übergeben wird. Wenn wir den Benutzernamen ’ OR 1=1--’
an die zweite Abfrage übergeben würden, würde einfach nach einem Benutzer gesucht, dessen Name mit ’ OR 1=1--’
übereinstimmt, vermutlich keinen finden und einen Fehler zurückgeben .
Es gibt viele weitere Details dazu, wie Datenbereinigung und parametrisierte Abfragen für komplizierte Datenbanken am besten implementiert werden können. Aus diesem Grund ist es wichtig sicherzustellen, dass Ihr Datenbankadministrator über die Tools und Kenntnisse verfügt, um Ihre Datenbankinfrastruktur ordnungsgemäß vor SQL-Injection-Angriffen zu schützen.