Einfacher Datenklau durch mangelnde Sicherheit

Wir haben in den letzten Wochen einige Datenbanken von Kunden untersucht und erhebliche Mängel bei der Sicherheit der Daten festgestellt. Primär haben wir uns angeschaut, ob ein Mitarbeiter ohne Weiteres auf die in der Datenbank gespeicherten Daten zugreifen kann. In den meisten Fällen konnte er sich einfach die Backend-Datenbank kopieren und so in den Besitz wichtiger Daten des Unternehmens gelangen. Oft war zumindest das Backend durch ein Kennwort geschützt, sodass man nur über das Frontend auf die Daten zugreifen kann. Ob das sicher ist, schauen wir uns im vorliegenden Beitrag an. Um es vorwegzunehmen: Es ist nicht sicher.

Trügerische Sicherheit? Noch nicht einmal das.

In einer Aktion, bei der wir uns die Datenbanken von Kunden angesehen haben, sind gravierende Sicherheitsmängel aufgetaucht:

  • Oft waren die Daten im Backend völlig ungesichert. Da die Benutzer schreibenden Zugriff auf die Backend-Datenbank benötigen, können sie theoretisch leicht die Backend-Datenbank kopieren und auf einen USB-Stick ziehen.
  • Teilweise haben wir zumindest per Kennwort geschützte Backenddatenbanken vorgefunden. Die Verknüpfung zu den Tabellen im Backend enthielt dann jedoch das Kennwort in den Verknüpfungseigenschaften, was sich ebenfalls leicht auslesen lässt.
  • In den meisten Fällen konnte der Benutzer über den Navigationsbereich direkt auf die verknüpften Tabellen zugreifen. Der Manipulation von Daten wie etwa geleistete Arbeitsstunden oder dem Gehalt sind so leicht möglich, wenn die entsprechenden Tabellen vorliegen.

Aber selbst wenn der Entwickler die Anwendung so weit geschützt hat, dass der Benutzer nicht auf die eingebundenen Tabellen zugreifen kann, lassen sich alle Daten von außen leicht auslesen. In diesem Beitrag zeigen wir, wie das funktioniert. Voraussetzung dafür ist, dass der Benutzer die Frontend-Datenbank geöffnet hat.

Daten auslesen per VBA

Wir legen dazu in einer neuen Datenbank die Prozedur aus Listing 1 an. Die Vorbedingung für ihre Funktion ist:

Public Sub DatenbankAuslesen()
     Dim db As DAO.Database
     Dim tdf As DAO.TableDef
     Dim rst As DAO.Recordset
     Dim objAccess As Access.Application
     Dim fld As DAO.Field
     Set objAccess = GetObject(, "Access.Application")
     Set db = objAccess.CurrentDb
     For Each tdf In db.TableDefs
         If Not Len(tdf.Connect) = 0 Then
             Debug.Print tdf.Name
             Set rst = db.OpenRecordset("SELECT * FROM " & tdf.Name, dbOpenDynaset)
             Do While Not rst.EOF
                 For Each fld In rst.Fields
                     Debug.Print fld.Name; ": ",
                     On Error Resume Next
                     Debug.Print fld.Value,
                     On Error GoTo 0
                 Next fld
                 Debug.Print
                 rst.MoveNext
             Loop
         End If
     Next tdf
End Sub

Listing 1: Auslesen der Inhalte der Tabellen einer anderen geöffneten Access-Datenbank

  • Die auszulesende Datenbank ist bereits geöffnet.
  • Die auslesende Datenbank mit unserer VBA-Prozedur wird erst danach geöffnet.

In der Prozedur erstellen wir ein Objekt des Typs Access.Application auf Basis des Aufrufs GetObject(, „Access.Application“). Unter den oben angeführten Voraussetzungen sollten wir damit einen Verweis auf die zu untersuchende Datenbank erhalten.

Danach weisen wir der Variablen db einen Verweis auf das Database-Objekt dieser Datenbank zu und durchlaufen die enthaltenen Tabellen. Für alle Tabellen, deren Eigenschaft Connect einen Wert enthält und die wir so als Tabellenverknüpfung identifizieren können, geben wir zunächst den Namen aus.

Danach erstellen wir ein Recordset auf Basis der aktuellen Tabelle und durchlaufen die enthaltenen Datensätze. Dabei geben wir jeweils den Namen und den Inhalt der Felder aus. Wir verwenden noch eine Fehlerbehandlung, wenn sich der Inhalt nicht direkt ausgeben lässt – zum Beispiel für Felder des Typs OLE-Objekt.

Wir können so sehr einfach alle Daten der verknüpften Tabellen im zu untersuchenden Frontend ausgeben.

Das dient nur Beispielzwecken – wenn wir die Daten sichern und beispielsweise in einer eigenen Datei speichern und diese mitnehmen wollten, wäre auch das einfach möglich.

Wir könnten einfach das Datenmodell nachbauen, in dem wir dieses auslesen und in einer neuen Datenbank reproduzieren. Dann können wir Tabelle für Tabelle und Datensatz für Datensatz die gewünschten Informationen in die Zieltabelle übertragen.

Übertragen der Tabellen der geöffneten Datenbank in die Zieldatenbank

Zum Übertragen des kompletten Inhalts einer Datenbank bedarf es gar nicht viel. Wir haben diese Funktion auf drei Routinen aufgeteilt:

  • Die erste heißt TabellenUebertragen und ermittelt einen Verweis auf das Database-Objekt der Datenbank mit den zu übertragenden Tabellen und durchläuft die TableDef-Objekte.
  • Dabei ruft sie für jede Tabelle die zweite Routine namens TabelleNachbauen auf. Diese kopiert die Tabellen und die enthaltenen Felder Stück für Stück.
  • Die dritte Prozedur DatenKopieren überträgt schließlich die Daten der Felder der Quelltabelle in die Zieltabelle.

Die Prozedur TabellenUebertragen

Die erste Prozedur verwendet die bereits bekannte Technik, um einen Verweis auf das Database-Objekt der geöffneten und auszulesenden Datenbank zu erhalten. Außerdem füllt sie eine weitere Database-Variable mit einem Verweis auf die eigene Datenbank (siehe Listing 2).

Public Sub TabellenUebertragen()
     Dim objAccess As Access.Application
     Dim dbSource As DAO.Database
     Dim dbTarget As DAO.Database
     Dim strSource As String
     Dim strSQL As String
     Dim tdfSource As DAO.TableDef
     Dim tdfTarget As DAO.TableDef
     
     Set objAccess = GetObject(, "Access.Application")
     Set dbSource = objAccess.CurrentDb
     Set dbTarget = CurrentDb
     Set dbSource = objAccess.CurrentDb
     strSource = dbSource.Name
     Debug.Print strSource
     
     For Each tdfSource In dbSource.TableDefs
         Select Case True
             Case Left(tdfSource.Name, 4) = "MSys"
             Case Else
                 Set tdfTarget = TabelleNachbauen(dbTarget, tdfSource)
                 DatenKopieren dbSource, dbTarget, tdfSource.Name, tdfTarget.Name
         End Select
     Next tdfSource
     
     Application.RefreshDatabaseWindow
End Sub

Listing 2: Hauptprozedur zum Einlesen der Daten der aktuellen Datenbank

Dann durchläuft sie alle TableDef-Objekte der Quelldatenbank und prüft bestimmte Eigenschaften des Tabellennamens. Wenn dieser mit MSys beginnt, wird die Tabelle nicht berücksichtigt. Hier können Sie noch weitere Ausnahmen hinzufügen. Für alle anderen Tabellen ruft die Prozedur die beiden Routinen TabelleNachbauen und Datenkopieren auf. Dabei übergibt sie im ersten Fall einen Verweis auf die Zieldatenbank und auf das zu kopierende TableDef-Objekt. Im zweiten Fall übergibt sie Verweise auf Quell- und Ziel-Database-Objekt und den Namen der zu übertragenden Tabelle.

Danach aktualisiert sie noch das Datenbankfenster, damit die zur Zieldatenbank hinzugefügten Tabellen direkt angezeigt werden können.

Die Funktion TabelleNachbauen

Diese Funktion nimmt den Verweis auf die Zieldatenbank sowie das TableDef-Objekt der zu kopierenden Tabelle aus der Quelldatenbank entgegen. Sie löscht zunächst bei deaktivierter Fehlerbehandlung eine gegebenenfalls bereits vorhandene Tabelle mit dem gleichen Namen wie die zu erstellende Tabelle (siehe Listing 3).

Public Function TabelleNachbauen(db As DAO.Database, tdfSource As DAO.TableDef) As DAO.TableDef
     Dim fldSource As DAO.Field
     Dim fldTarget As DAO.Field
     Dim tdfTarget As DAO.TableDef
     
     On Error Resume Next
     db.TableDefs.Delete tdfSource.Name
     On Error GoTo 0
     
     Set tdfTarget = db.CreateTableDef(tdfSource.Name)
         
     For Each fldSource In tdfSource.Fields
         Set fldTarget = tdfTarget.CreateField(fldSource.Name, fldSource.Type, fldSource.Size)
         If fldTarget.Type = dbText Then
             fldTarget.AllowZeroLength = True
         End If
         tdfTarget.Fields.Append fldTarget
     Next fldSource
     
     db.TableDefs.Append tdfTarget
     
     Set TabelleNachbauen = tdfTarget
End Function

Listing 3: Funktion zum Reproduzieren der Tabellen und Felder

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar