Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.
Sichere Filterausdrücke
Filterausdrücke können schnell gefährlich werden, zumindest wenn Sie nicht aufpassen. Dafür sorgt die sogenannte SQL-Injection, bei der davon ausgegangen wird, dass der Benutzer einen Ausdruck in die Benutzeroberfläche eingibt, die dann als Teil eines SQL-Ausdrucks verwendet wird und Schaden anrichten könnte. Dieser Beitrag erläutert, was SQL-Injection eigentlich ist und wie Sie sich dagegen wappnen können.
Die SQL-Injection ist eine Methode, aus eigentlich harmlosen SQL-Anweisungen schädliche SQL-Anweisungen zu machen – oder damit an Informationen zu gelangen, die der Benutzer normalerweise nicht erhalten sollte. Dabei ist die Voraussetzung immer ein Eingabefeld in einer Webseite oder, in diesem Falle, in einem Access-Formular, in das der Benutzer beispielsweise einen Vergleichswert für einen Vergleichsausdruck eingeben soll – im einfachsten Fall etwa die ID eines Kunden.
Beispielformular
Als Spielwiese für die folgenden Beispiele verwenden wir ein einfaches Access-Formular namens frmKunden samt Unterformular sfmKunden, wobei das Unterformular die Daten der Tabelle tblKunden anzeigt und das Hauptformular ein Eingabefeld für einen Suchbegriff liefert, der zunächst die Suche nach Werten im Feld KundeID ermöglicht (s. Bild 1).
Bild 1: Beispielformular in der EntwurfsansichtFür das Textfeld txtKundenID legen wir die folgende Ereignisprozedur an:
Private Sub txtKundenID_AfterUpdate()
Dim strSQL As String
strSQL = "SELECT * FROM tblKunden WHERE KundeID = " & Me!txtKundenID
Me!sfmKunden.Form.RecordSource = strSQL
End Sub
Diese sorgt dafür, dass eine neue SQL-Anweisung zusammengestellt wird, die den Datensatz der Tabelle tblKunden mit einem bestimmten Wert im Feld KundeID liefert und diesen der Eigenschaft RecordSource des Unterformular zuweist. Dies gelingt auch reibungslos, wenn der Benutzer einfach nur einen Zahlenwert eingibt (s. Bild 2).
Bild 2: Filtern nach dem Wert 1 im Feld KundeID
Ergebnismenge mit UNION erweitern
Was an unserer Methode soll also gefährlich sein – schließlich kann man doch nur Zahlenwerte eingeben und erhält das gewünschte Ergebnis? Mitnichten: Schon die Kenntnis der Datenstruktur (oder ein wenig experimentelle Arbeit) erlauben es, ein ganz anderes Ergebnis zu erhalten als geplant. Geben Sie beispielsweise einmal den folgenden Ausdruck in das Suchfeld ein:
1 UNION SELECT * FROM tblKunden WHERE KundeID = 10
Das Ergebnis ist überraschend: Es gibt keinen Fehler, sondern es erscheinen zwei Datensätze (s. Bild 3)! Allzu verwunderlich ist dies jedoch gar nicht, denn der resultierende Ausdruck in der Variablen strSQL, den Sie sich einfach im Debugbereich ausgeben lassen können, sieht wie folgt aus:
Bild 3: Erweiterung des Ergebnisses per UNIONSELECT * FROM tblKunden WHERE KundeID = 1
UNION
SELECT * FROM tblKunden WHERE KundeID = 11
Gut, der Schaden ist gering, denn wir greifen so nur auf Datensätze zu, die wir auch anderweitig hätten lesen können. Aber wenn wir keine Bedingung angeben, liefert der resultierende SQL-Ausdruck uns sogar wieder alle Datensätze:
SELECT * FROM tblKunden WHERE KundeID = 1
UNION
SELECT * FROM tblKunden
Dies könnte interessant werden, wenn der eigentliche Filterausdruck noch dafür sorgt, dass beispielsweise nur die Kunden des aktuell angemeldeten Mitarbeiters angezeigt werden sollen.
Daten anderer Tabellen auslesen
Noch spannender wird es, wenn Sie hinter dem UNION -Schlüsselwort nicht auf die gleiche, sondern direkt auf eine andere Tabelle zugreifen, die unter Umständen kritische Daten enthält. Im Beispiel wollen wir einfach einmal probieren, Daten aus der Tabelle tblArtikel zusätzlich auszugeben, und testen den folgenden Suchausdruck:
1 UNION SELECT ArtikelID as KundeID, Artikelname as Kundencode FROM tblArtikel
Dies liefert im ersten Anlauf noch den Fehler aus Bild 4, weil der zweite Teil der UNION-Abfrage nicht die gleiche Anzahl Felder wie der erste Teil zurückliefert. Aber was geschieht, wenn wir einfach ein paar fixe Werte entsprechend der Anzahl der Felder des ersten Teils der Abfrage hinzufügen – und so notfalls durch Experimentieren auf die richtige Anzahl Felder kommen? So ergibt sich nach kurzem Test der folgende Ausdruck:
Bild 4: Fehler, wenn nicht alle Seiten der UNION-Abfrage die gleiche Anzahl Felder enthalten1 UNION SELECT ArtikelID as KundeID, Artikelname as Kundencode, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 FROM tblArtikel
Das Ergebnis ist einigermaßen erschreckend: Wir gelangen so tatsächlich an die Informationen der Tabelle tblArtikel, die eigentlich gar nicht zur Datenherkunft des Unterformulars gehört (s. Bild 5). Und natürlich könnten wir diese Tabelle auch durch eine Tabelle mit wirklich sensiblen Daten wie etwa der Benutzertabelle ersetzen.
Bild 5: Ermitteln der Daten einer anderen Tabelle
So lassen sich auch leicht die Tabellen einer Datenbank ausgeben – und zwar mit diesem Suchbegriff:
1 UNION SELECT Name, Type , 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 FROM MSysObjects WHERE Type = 1
Gefährliche Strings
Gibt es ebenfalls Probleme, wenn man ein Suchfeld für die Eingabe einer Zeichenkette verwendet? Ja. Dazu fügen wir dem Formular ein Textfeld namens txtFirma hinzu, das nach dem Aktualisieren die folgende Ereignisprozedur auslöst:
Private Sub txtFirma_AfterUpdate()
Dim strSQL As String
Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.