[DE] Unterschätzte Gefahr: SQL-Injections

in #neulingschallenge6 years ago

banner

Ich war immer der Meinung, dass die Zeit für SQL-Injections abgelaufen sei. Doch als ich vor wenigen Tagen hier auf steemit einen Post lesen musste, welcher auf fahrlässige Weise zeigt, wie man nicht mit SQL arbeiten sollte, wurde mir klar, dass dem nicht so ist. Dieser Post handelt nun also über SQL-Injections, was sie sind und wie man sich dagegen schützen kann.


Was sind SQL-Injections?

SQL-Injections sind eine Form des Angriffs auf datenbankbasierte Anwendungen. Nicht nur reine Web-Anwendungen, sondern auch alle Anwendungen, welche eine SQL-Datenbank integriert haben, sind davon betroffen[1]. Bekannte Beispiele für weitere Angriffsflächen sind Microsoft Access oder dBase von Borland. Der Zweck hinter SQL-Injections ist die Manipulation der von der Applikation benutzten SQL-Datenbank[2]. So können unauthentifizierte Zugriffe, das Löschen aller Daten oder der Diebstahl von Kreditkarteninformationen das Ziel der Angreifer sein. Meist erfolgen solche Angriffe über eine von der Applikation zur Verfügung gestellte Schnittstelle, welche nicht gegen schädliche Nutzereingabe gesichert wurde.

Ziele und Beispiele von SQL-Injections

Im vorherigen Kapitel bereits angesprochen, kann man mit SQL-Injections verschiedene Ziele verfolgen. In den folgenden Unterkapiteln möchte ich auf ein paar mögliche Ziele eingehen und zeige dazu, wie ein solcher Angriff aussehen könnte.
Bevor man sich jedoch einem solchen Angriff widmen kann, muss man sich sein Opfer genau vorstellen können. In unserem Fall wird es sich beispielsweise um eine webbasierte Anwendung handeln. Diese kann verallgemeinert aus folgenden Komponenten bestehen:

KomponenteAufgabe
ClientIst die Oberfläche, welche dem Benutzer eine Schnittstelle zum Server bietet
ServerLiefert dem Client Ressourcen und ist die Schnittstelle zwischen Client und Datenbank
DatenbankBeinhaltet Datensätze und ist Ziel unseres Angriffes

Wenn nun der Code, welcher für die Kommunikation zwischen dem Server und der Datenbank zuständig ist, Schwachstellen in der Implementierung aufweist und zum Beispiel jede Anfrage des Nutzers ungefiltert an die Datenbank weiterleitet, kann es zu schwerwiegenden Eingriffen kommen.

Das gewöhnliche "Login-Query"

Betrachten wir einen gewöhnlichen SQL-Befehl, um in einer Tabelle mit Nutzern nach einem speziellen Nutzer mit Name und Passwort zu suchen: SELECT * FROM users WHERE name='@sidem' AND password='qwertz';. Wird nun ein Nutzer mit Namen @sidem und dem Passwort qwertz gefunden, wird er zurück gegeben. Für die folgenden Beispiele werden wir diesen SQL-Befehl als Grundlage der Login-Routine verwenden, welche wir angreifen wollen.

Authentifizierung umgehen

Möchten wir uns nun Zugriff zu einem geschützten Bereich verschaffen, haben wir mehrere verschiedene Möglichkeiten dies zu tun:

Authentifizierung als willkürlicher Benutzer

Die erste Möglichkeit besteht darin, dass wir uns als willkürlicher Benutzer versuchen zu authentifizieren. Das bedeutet, dass es für uns keine Rolle spielt, mit welchem Nutzer wir angemeldet werden und oder welche Rechte dieser besitzt. Damit wir dieses Ziel erreichen, müssen wir dafür sorgen, dass der SQL-Befehl unserer Login-Routine wie folgt abgeändert wird:
SELECT * from users WHERE name='' AND password='' OR 1=1;
Die kleine Änderung OR 1=1 nenn man Tautologie und bedeutet, dass die Bedingung für sämtliche Datensätze erfüllt ist.

Authentifizierung als bestimmter Benutzer

Die zweite Möglichkeit besteht darin, dass wir uns als bestimmter Benutzer versuchen zu authentifizieren. Dazu müssen wir den SQL-Befehl abermals wie folgt abändern:
SELECT * from users WHERE name='' AND password='' OR name='@security101';
Entscheidend bei diesem Befehl ist abermals der hintere Teil der Bedingung OR name='@security101'. Mit dieser Änderung, wird dafür gesorgt, dass egal welches Passwort auch eingegeben wurde, der Datensatz des Nutzers mit dem Namen @security101 zurückgegeben wird.

Angriff auf ein unbekanntes System

Doch wie geht man vor, wenn man ein unbekanntes System vor sich hat? Wenn man nicht den internen Code zur Verfügung hat?

Stellen wir uns folgendes Szenario vor: wir stoßen auf eine Webseite, welche wir vor langer Zeit selbst geschrieben haben und sehen nichts außer einem Login-Formular.


Nur gut, dass wir damals diesen Post noch nicht kannten und somit sicherlich scheunentorgroße Lücken in der Implementierung haben.

Schritt 1: Testen auf Lücken

Der erste Schritt ist denkbar einfach. Wir müssen einen Fehler auf Datenbank-Ebene provozieren. Dazu probieren wir es mit in SQL verwendeten Sonderzeichen, in unserem Fall mit einem Apostroph '. Bekommen wir nun eine Fehlermeldung wie in dem Bild gezeigt, bedeutet dies, dass die Anwendung angreifbar ist.
sql-injection-error

Schritt 2: Informationen sammeln

Ein essentieller Teil beim Pentesting (oder auch hacken), ist das Sammeln von Informationen. In unserem Fall möchten wir wissen, aus wie vielen Spalten die Tabelle besteht, welche mit dem Login-Formular in Verbindung steht. Dazu benutzen wir den SQL-Befehl ORDER BY x, welcher die Datensätze nach der xten Spalte sortieren soll. Wir ersetzen x inkrementell durch einen höheren Integer-Wert, bis wir abermals einen Fehler erhalten. Somit wissen wir dann, dass die Tabelle aus x - 1 Spalten besteht.
Diese Information ist nützlich für

Schritt 3: Ausführung

Möchten wir in der Anwendung andere Daten ausgeben lassen, als die Anwendung es vielleicht vorsieht, können wir dazu den Befehl UNION ALL benutzen. Dieser vereint die Ergebnismengen zweier Abfragen. Nutzen wir diesen mit zum Beispiel SELECT 1,2,3,4 würden wir in unserer unbekannten Anwendung folgendes erhalten:
sql-injection-union-all
Daraus lässt sich schließen, dass name die Spalte Nummer 2 ist und, dass offenbar Adress-Daten in Spalte 4 stehen.
Mit diesem Wissen lässt sich nun jede beliebe Information an diese Stellen der Applikation einpflanzen. Zum Beispiel die Versionsnummer der Datenbank mit UNION ALL SELECT 1,@@Version,3,4.
An diesem Punkt des Angriffs, sind der Fantasie keine Grenzen mehr gesetzt. So kann je nach Berechtigung des Datenbanknutzers die Datenbank mit DROP DATABASE testdb gelöscht werden, nachdem man mit UNION ALL SELECT 1,group_concat(SCHEMA_NAME),3,4FROM information_schema.SCHEMATA den Datenbanknamen erfahren hat.

Schutzmaßnahmen

Wie man eine Anwendung angreift wissen wir nun. Nun geht es darum, wie man diese vor SQL-Injections schützen kann.
Vorher möchte ich darauf hinweisen, dass es KEINEN 100%igen Schutz geben kann. Alle hier erwähnten Schutzmaßnahmen tragen lediglich dazu bei, die allgemeine Sicherheit zu erhöhen.

Prepared-Statements

Prepared-Statements sind vorbereitete Befehle mit Platzhaltern anstelle von Variablen. Der Zweck solcher Befehle liegt in der Optimierung der Verarbeitung. Der Befehl selbst und die dazugehörigen Parameter werden getrennt versendet. Dadurch entsteht der Vorteil, dass bei häufigen Aufrufen desselben Befehls lediglich die Parameter neu gesendet werden müssen und die Befehle dadurch schneller ausgeführt werden können.
Für den Sicherheitsaspekt helfen Prepared-Statements, da sie die Parameter auf Datentypen überprüfen und dabei Sonderzeichen und eventuell auftretende SQL-Befehle entfernen.

Rechteverwaltung

In unserem Beispiel-Angriff haben wir die Datenbank testdb löschen können, da der jeweilige Datenbanknutzer, mit welchem dieser Befehl ausgeführt wurde, die Berechtigung dazu hatte. Hat man nun Rechtegruppen, welche so aufgeteilt werden, dass sie nur die Rechte besitzen, die von der Applikation benötigt werden, kann man potentielle Gefahren abwenden.

Fazit

Das Entwickeln von gegen SQL-Injections geschützten Anwendungen ist mindestens so einfach wie die Ausführung einer einfachen SQL-Injection selbst. Somit sollte es keinen Grund geben seine Anwendung nicht abzusichern, wobei gerade Prepared-Statements sogar noch einen kleinen Geschwindigkeitsvorteil mit liefern.

Quellen

[1]http://archiv.infsec.ethz.ch/education/projects/archive/sqliadReport.pdf (besucht am 09.02.2018 11:10)
[2]https://www.barracuda.com/glossary/sql-injection (besucht am 09.02.2018 11:15)

Dieser Posts ist eine Aufarbeitung einer wissenschaftlichen Arbeit, welche mit @patlongus geschrieben wurde.


Du hast Fragen, Änderungsvorschläge oder Wünsche? Lass es mich in den Kommentaren wissen 😉
In dem Sinne, frohes Coden.



credits:@carlos-cabeza

Sort:  

This is a test comment, notify @kryzsec on discord if there are any errors please.


GuidelinesProject Update

Being A SteemStem Member

Sehr interessanter Beitrag und Top geschrieben !

Erschreckend wie oft Datenbankanfragen nicht geschützt sind..

Dankeschön!

Vorallem ist es traurig, da es ja kein großer Mehraufwand ist es sicher zu implementieren.

Danke für diesen informativen Beitrag, aber das ist ein Thema mit dem ich null anfangen kann. Ich versteh nur Bahnhof. Werde ihn mir später nochmal des besseren Verständnisses wegen genauer durchlesen!

Gerne doch. Eventuell können dir deine Follower helfen, wenn du diesen Post resteemst 😉
Spaß beiseite: das Thema ist super wichtig, um als Entwickler keine Sicherheitslücken aufzureißen und als Nutzer keine unerwarteten Überraschungen zu erhalten (z.B. Kreditkartenklau).

PreparedStatements sind unglaublich nützlich, um SQL Injections zu umgehen. Sobald es um irgendwelche Nutzerdaten geht, verwende ich sie. Außerdem sind sie ganz einfach zu benutzen. Sobald man einmal über SQL Injections aufgeklärt wurde, unterläuft einem eigentlich kein Fehler mehr.

Da gebe ich dir recht.

Ist schon ein spannendes Thema. Die Dunkelziffern sind doch meistens sehr hoch, was wohl auch daran liegt das es keiner merkt.

Toller und Informativer post

Ja, das stimmt. Gerade wenn sich sich den Spaß macht irgendwo ein ' einzufügen wird man häufig überrascht, dass man wirklich mit einem Fehler begrüßt wird.

Das sorgt dann für Laune :P

Klasse Artikel. Vielen Dank!
Das thema ist super wichtig. Für Entwickler sowieso aber auch für den normalen Anwender. Denn nur wer eine Gefahr versteht kann sich entsprechend verhalten...

Dankeschön!
Ich teile deine Ansicht zu 100%. Aber leider ignorieren viele die Risiken...

Congratulations @drookyn! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

Upvote this notification to help all Steemit users. Learn why here!

Coin Marketplace

STEEM 0.27
TRX 0.13
JST 0.032
BTC 60826.65
ETH 2907.17
USDT 1.00
SBD 3.54