Architektur-Probleme bei Datenbank-Systemen mit Vielfach- und Web-Zugriff

1. Vorbemerkung

Basierend auf der Unterscheidung zwischen Datenbank und Datenbankmanagement-Systemen (siehe Datenbank-Grundbegriffe ) muß zunächst unterschieden werden zwischen Datenbankmanagement-Systemen im engeren und im weiteren Sinne. Erstere umfassen Produkte wie Microsoft Access, Filemaker oder dBase als dateibasierte Systeme sowie serverbasiert-aktive Produkte wie Adabas, DB2, FireBird, Informix, Microsoft Sql Server, mySql, PostGreSQL und Oracle. Aufbauend auf einem dieser Systeme gibt es zahllose individuelle Lösungen erweiterter DBMS, welche das Grundsystem um eigene Benutzermasken, ein weitergehendes Sicherheitskonzept oder vorgefertigten Routinen für spezielle Branchen erweitern. Alle erweiterten Datenbankmanagement-Systeme organisieren den Datentransport zwischen den Daten eingebenden Mitarbeitern und dem DBMS im engeren Sinne und werden im folgenden als Datenmanagement-Systeme (DMS) bezeichnet. Das Spektrum für ein DMS reicht von einem Null-DMS, bei welchem die rohen Access-Tabellen direkt zur Dateneingabe verwendet werden, über kleine webbasierte Lösungen basierend auf Access, Filemaker oder mySql bis hin zu mittleren branchenspezifischen (Bibliotheken, Hochschulverwaltung, Krankenhäuser) oder branchenübergreifenden großen Systemen (mySAP ERP Financials von SAP, Applications von Oracle). Die folgenden Ausführungen befassen sich mit der Frage, welche Sicherheitsprobleme bei kleinen und mittleren Systemen auftreten können und welche Kriterien aus der Perspektive eines Datenbank-Entwicklers zu beachten sind.

2. Ein Beispiel

Ein Mitarbeiter in einer kleinen Firma definiert sich eine Access-Datenbank mit einigen Tabellen, die er zunächst auf seinem eigenen Rechner nutzt. Die Dateneingabe erfolgt direkt in den Tabellen oder in Form einfacher, per Assistent erzeugter Masken. Die Daten sind auch für andere Mitarbeiter nützlich, also wird die Datenbank-Datei auf einen Server verschoben und von mehreren Personen verwendet. Inzwischen ist die Firma gewachsen und es wurden Tabellen hinzugefügt, die nicht mehr allen Mitarbeitern zugänglich sein sollen. Da jedoch, selbst bei der Verwendung der Access-internen Nutzerkonfiguration, jedem Nutzer vom Betriebssystem her Schreibzugriff auf die Datei gestattet sein muß, kann jeder Nutzer 'aus Versehen' die Datenbank physikalisch löschen. Eine Sicherung ist nur durch Kopieren der MDB-Datei möglich. Dies kann vergessen werden, da es sich innerhalb von Access nicht automatisieren läßt. Ferner wäre es wünschenswert, daß eine Teilmenge der Daten in die Firmenhomepage eingebunden wird. Hierbei entwickelt sich die Frage, ob nicht externe Leser Informationen übermitteln könnten, die nach Überprüfung durch einen Firmenmitarbeiter entweder auf der Homepage lesbar sind oder Firmenaktivitäten (Bestellungen) anstoßen. Eine Zusendung der Daten per Mail ist zwar technisch einfach, führt jedoch zur sinnlosen Doppelarbeit des erneuten Eingebens.

3. Filebasierte Lösungen versus Systeme, die auf aktiven Datenbankmanagement-Systemen basieren

Es gibt Schreibzugriffe, welche viele Einzeloperationen umfassen: Bei einem Datensatz werden mehrere Zellen gemeinsam geändert, innerhalb einer Operation müssen zwei Zeilen hinzugefügt werden (Bsp. Umbuchung zwischen zwei Konten) oder es wird das Schema einer Tabelle erweitert, die bereits Daten enthält (Hinzufügen einer Spalte, Änderung eines Datentyps). Oder es sollen alle Änderungen protokolliert werden, so daß die Änderung einer Zeile nur zusammen mit einem Protokolleintrag erfolgt bzw. beide Operationen scheitern, da die Protokollierung nicht durchgeführt werden kann. Analoge Vielfachzugriffe, die nach außen hin eine atomare Einheit bilden, treten auf, falls mehrere Nutzer Datensätze lesen und diese ändern. Hier kann das DBMS noch mit dem Festschreiben einer Änderung beschäftigt sein, während bereits der nächste Lesezugriff oder Schreibversuch erfolgt. All diese komplexen Operationen können durch Stromausfall, Netzwerkprobleme und ähnliches unterbrochen werden, so daß sich die Frage nach der Konsistenz der Datenbank stellt. Ein Verlust der Datenbank-Konsistenz bedeutet im kritischen Fall die Unverarbeitbarkeit der Datei, damit den Verlust sämtlicher Daten, so daß auf die letzte Sicherung zurückgegriffen werden muß. Damit sind auch alle Änderungen zwischen der letzten Sicherung und dem Ausfall vernichtet. Wird die Datenbank nur von einer Person genutzt, so mögen sich die Änderungen zwischen der letzten Sicherung und dem Kollaps noch reproduzieren lassen. Hat das DMS jedoch Bestellungen aus dem Internet entgegengenommen oder werden Daten von diversen Mitarbeitern innerhalb einer größeren Einrichtung von verschiedenen Standorten her eingegeben, so dürften diese unwiderruflich verschwunden sein. Dies gilt in besonderer Weise für Einrichtungen mit Publikumsverkehr, bei welchen die Daten der Kunden von Mitarbeitern sofort am Bildschirm eingegeben werden, so daß der Einrichtung keine Papierversion zur Verfügung steht.

Bezüglich dieser Gefahr des Datenverlustes reagieren passive bzw. aktive DBMS verschiedenartig. Bei der Verwendung eines passiven Systems konkurrieren alle CPUs der aktuell zugreifenden Clientrechner um eine Ressource, die CPU des Servers stellt lediglich Dateisystem-Zugriffe bereit. Bricht eine Verbindung ab oder fällt der Server aus, so bleiben die unvermeidlichen Inkonsistenzen und die gesetzten Sperren innerhalb großer Schreibzugriffe zunächst bestehen. Sie können korrekt aufgelöst werden - oder die Datenbank bleibt inkonsistent, dann bleibt nur der Rückgriff auf die letzte Sicherung. Gänzlich anders verarbeitet ein aktives Backend diese Situation: Hier werden die Zugriffswünsche in eine Warteschlange gestellt und vom DBMS, also von der CPU des Datenbank-Servers, konsistent abgearbeitet. Bricht nun eine Netzwerkverbindung ab, so bemerkt das DBMS dies und bereinigt alle von dieser Verbindung belegten Ressourcen unverzüglich. Fällt bei einem aktiven System der Strom aus, so daß die Arbeit der CPU unmittelbar stoppt, so findet diese Bereinigung beim nächsten Start des DBMS automatisch statt. Ein korrekt konfiguriertes aktives System kann deshalb auch nach einem Stromausfall alle Daten wiederherstellen, die bis unmittelbar vor den Ausfall eingegeben worden sind. Meistens genügt es, das DBMS erneut zu starten. Zusätzliche Sicherungen lassen sich automatisch per Job erstellen. Die Datendateien sind gegenüber allen Benutzern verborgen, eine versehentliche Löschung ist unmöglich. Insgesamt ergibt sich, daß jedes Datenmanagementsystem, welches eine ernstzunehmende Mehrfachnutzung zu unterstützen behauptet, ausschließlich aktive Backends unterstützen darf. Wird umgekehrt ein DMS angeboten, welches als Backend sowohl filebasiert / passive als auch serverbasiert / aktive Systeme unterstützt, so wurde diese fundamentale Designentscheidung bei der Konzeption dieses Systems ignoriert. Der Hersteller dieses DMS erzeugt Laien gegenüber die Illusion, daß die Daten in einem solchen System 'hinreichend sicher' seien, so daß die Kosten für ein aktives System eingespart werden könnten.

4. Eingeschränkte Zugriffsrechte und Einbruchsversuche

Bei der Konzeption eines Datenbanksystems für mehrere Nutzer ist davon auszugehen, daß einzelne Personen mit allen ihnen zur Verfügung stehenden Mitteln versuchen, unberechtigt auf Daten zuzugreifen, sei es, um diese zu lesen oder um sie zu ändern. Für die Konzeption einer Datenbank-Anwendung ist dies nicht eine ignorierbare Ausnahme, sondern ein Sachverhalt, mit welchem jederzeit zu rechnen ist. Dies gilt unabhängig von der Frage, ob auf die Datenbank per Web lesend oder schreibend zugegriffen wird. Auch bei Systemen, die ausschließlich in einem geschlossenen Netzwerk eingesetzt werden, gibt es Konkurrenz unter den Mitarbeitern. In jeder größeren Einrichtung ist mit 'schwarzen Schafen' zu rechnen, einem Mitarbeiter mag gekündigt worden sein, er versucht, sich zu rächen oder anderen Mitarbeitern etwas anzuhängen. Ein Datenmanagement-System sollte deshalb durch klare Verantwortlichkeiten charakterisiert sein. Schließlich können Administratoren Fehler unterlaufen, die - in Abhängigkeit vom DMS - minimal-harmlose oder existenzbedrohende Wirkungen entfalten. Als Richtschnur für all diese Anforderungen hat sich als zentrales Konzept das Prinzip der minimalen Rechte (Principle of least Privilege) bewährt: Dieses Prinzip gilt zunächst für die Vergabe der Benutzerrechte. Sie müssen hinreichend ausdifferenziert festgelegt werden können, es ist zu unterscheiden zwischen dem eigentlichen Lese/Schreibrecht pro Tabelle sowie der Verwaltung dieser Nutzerrechte selbst. Es korrespondiert bsp. damit, daß in einer größeren Einrichtung nicht jeder Mitarbeiter einen Generalschlüssel erhält. Ausdifferenzierte Rechte können jedoch nur dann vom DMS durchgesetzt werden, falls sie nicht übergangen werden können. Das Prinzip der minimalen Rechte für Nutzer ist folglich nur wirksam, falls es für die Architektur des DMS selbst gilt. Hierbei ist allerdings zu beachten: Leser mögen beachten, daß dem Verfasser zwar derzeit keine dieser Techniken konkret bekannt sind. Jedoch zeigt die Entwicklung der letzten Jahre, daß in so gut wie jeder Grundsoftware sicherheitsrelevante Bugs zu finden sind. Ferner sind heutige Betriebssysteme um Dimensionen komplexer geworden als noch vor fünf oder zehn Jahren und enthalten bereits bei der Auslieferung diverse Debug-Werkzeuge. Kritische Lücken können durch die Kombination einzelner, für sich selbst betrachtet winziger Manipulationen entstehen. Das Design eines DMS muß deshalb dafür sorgen, daß solche sicherheitsrelevanten Bugs keine allzugroßen Folgeschäden ermöglichen. Das Prinzip der minimalen Rechte angewandt auf ein Datenmanagementsystem bedeutet:

5. Zweistufige versus drei- und mehrstufige Architekturen

Unter einer zweistufigen DMS-Architektur wird ein System verstanden, bei welchem sich der Client direkt mit dem Datenbankmanagement-System verbindet. Bei einem dreistufigen System verbindet sich der Client (Client-I) mit einem anderen Rechner, der gegenüber diesem Client als Server fungiert und sich selbst als Client (Client-II) am Datenbankmanagement-System anmeldet. Letzteres läuft in der Regel auf einem dritten Rechner.

Für ein zweistufiges System sind die folgenden Merkmale charakteristisch: Ein dreistufiges System erlaubt eine Trennung der verschiedenen Zugriffsebenen und sollte die folgenden Merkmale aufweisen: Die letzten Beispiele verdeutlichen, wie unterschiedlich die Folgen eines erfolgreichen Einbruchs sein können. Verwendet der Client-II eine DBMS-Verbindung mit Systemadministrator-Berechtigung, so gehört dem Hacker unmittelbar nach dem Einbruch in den Client-II das gesamte Datenbankmanagement-System. Wird dagegen eine schwache Verbindung genutzt, die lediglich innerhalb einer Datenbank gespeicherte Prozeduren ausführen darf, so kann kein unmittelbarer Schaden erzeugt werden, da die nächste Barriere folgt. Beauftragt eine Firma Externe mit der Entwicklung einer Datenbank-Anbindung an eine Website, so ist darauf zu achten, daß nicht aus falscher Bequemlichkeit oder zur Zeitersparnis eine unnötig starke Verbindung zwischen Web- und Datenbankserver genutzt wird.

Zusammengefaßt gilt: Unter Sicherheitsgesichtspunkten ist jedes zweischichtige System inakzeptabel. Entweder kann die Protokollierung nur mit dem Passwort des Nutzers durchgeführt, also auch von diesem gelöscht werden. Oder die Verbindung wird hochgestuft, hierfür benötigt der Client ein stärkeres Passwort. Dies läßt sich spätestens mit Debug- oder Hackertechniken aushebeln. Für die Microsoft-Welt ist jedes zweistufige Konzept seit etwa 1998, seit der Veröffentlichung von ADO sowie Hinweisen zu dreischichtigen Architekturen, nicht mehr zeitgemäß.

6. 'Trau nie, nie, nie Benutzereingaben' - oder: 'Wie hacke ich mit Sql-Injections eine Datenbank?'

Sämtliche bislang vorgestellten Prinzipien sind nutzlos, falls der Webserver bsp. eine Login-Maske anbietet und einen Code wie folgt enthält:
Dim oConn As New SqlConnection("Server=(local);Trusted_Connection=Yes"), _
	oCmd As New SqlCommand("", oConn), _
	oDA As New SqlDataAdapter(oCmd), _
	oDS As New DataSet(), _
	str_Cmd As String

str_Cmd = "Select Count(*) From Kunden
	Where Kundenname = '" & _
	Me.Request.Form("User_Name") & "' And Passwort = '" & _
	Me.Request.Form("User_Password") & "'"

oCmd.CommandText = str_Cmd

oDA.Fill(oDS, "Kunden")

If CType(oDS.Tables("Kunden").Rows(0)(0), Integer) > 0 Then
	'Login erlauben
Else
	'Ungültiger Nutzername und / oder Passwort
End If
Wer aufgrund der obigen Hinweise einwendet, er würde nur gespeicherte Prozeduren verwenden und sei deshalb gefeit, der betrachte den folgenden Code:
oCmd.CommandText = "Execute check_Login '" & _
	Me.Request.Form("User_Name") & _
	"', '" & Me.Request.Form("User_Password") & "', " & _
	Me.Request.Form("Type")
Die gespeicherte Prozedur soll durch den folgenden Befehl erzeugt worden sein:
Create Procedure check_Login
	@User_Name nvarchar(50),
	@User_Password nvarchar(50),
	@type int

As

Select Count(*)
From Kunden
Where Kundenname = @User_Name And
	Passwort = @User_Password And
	Type = @type
Der Code mag für Laien harmlos erscheinen. Die Benutzereingaben werden zu einem String verkettet und dieser als Befehl an die Datenbank weitergereicht. In Abhängigkeit vom Ergebnis wird das Login erlaubt oder eine Fehlermeldung ausgegeben. Vergleichbare Beispiele finden sich selbst in Anleitungen von Providern für die Entwicklung einer Datenbank-Anwendung mit Webzugriff.

Der Code funktioniert korrekt, falls lediglich die gewünschten Daten eingegeben werden. Mustermann als Name und topsecret als Passwort erzeugt den Befehl
Select Count(*) From Kunden
Where Kundenname = 'Mustermann' And Passwort = 'topsecret'
Dieser ist syntaktisch korrekt und wird ausgeführt. Wird als Name O'Neill gewählt, so ist der entstehende Ausdruck syntaktisch falsch, da ' als Sonderzeichen nicht direkt verwendet werden darf:
Select Count(*) From Kunden
Where Kundenname = 'O'Neill' And Passwort = 'topsecret'
Der Ms-SqlServer erwartet als gültigen Textvergleich einen Ausdruck O''Neill, bei mySql wird mit O\'Neill maskiert. Der entstehende Ausdruck wird vom DBMS bei der Syntaxprüfung zurückgewiesen, so daß - glücklicherweise - kein Code ausgeführt wird. Mit diesem Wissen kann man jedoch die Logik der Abfrage verändern: Ein Name test' -- und ein beliebiges Passwort führt beim Ms-SqlServer zu dem nun syntaktisch korrekten Code:
Select Count(*) From Kunden
Where Kundenname = 'test'
Da mit -- alles bis zum Zeilenende auskommentiert wird, wird das Passwort nicht mehr geprüft, die Abfrage ist erfolgreich, falls es einen Benutzer test gibt. Besser ist natürlich die Eingabe ' Or 0 = 0 --, da der entstehende Befehl
Select Count(*) From Kunden
Where Kundenname = '' Or 0 = 0
erfolgreich ist, falls ein einziger Kunde eingetragen ist. Und wirklich wirksam wird die Anweisung, falls ein wenig mehr getippt wird: ' Delete From Kunden --. Der ausgeführte Befehl
Select Count(*) From Kunden
Where Kundenname = '' Delete From Kunden
ermöglicht zwar kein Login mehr, es gibt jedoch anschließend auch keine Einträge mehr in der Kundentabelle. Es kann natürlich weiterhin über eine solche Logon-Maske Sql-Code ausgeführt werden, so daß, bei einer hinreichend starken Verbindung zum DBMS, mit
' Execute master.dbo.sp_addlogin 'newUser',
	'this is now my server'
Execute master.dbo.sp_addsrvrolemember 'newUser',
	'sysadmin' --
ein neuer Benutzer 'newUser' mit dem Passwort 'this is now my server' erstellt und dieser als Systemadministrator definiert wird. Falls das Html-Eingabeformular auf 20 Zeichen begrenzt ist, baut man sich rasch ein eigenes Formular, das hält einen Kundigen nicht auf. Für die Ausführung einer gespeicherten Prozedur durch eine String-Verkettung gilt dasselbe Problem. Und enthält die Parameterliste Zahlen, so sind einfache Hochkommata bzw. deren nicht korrekte Verarbeitung nicht einmal notwendig, ein 'Delete' kann, durch Leerzeichen getrennt, direkt angefügt werden.

Diese Gefährdung existiert, falls die Benutzereingaben direkt übernommen werden, um sie mit weiteren Bausteinen zu Sql-Code zusammenzufügen. Dabei ist es unerheblich, ob es sich um einen Browser oder bsp. um Access als Clientprogramm handelt. Entscheidend ist, wie die nächste Instanz die Nutzereingaben verarbeitet. Der Schutz vor solchen Sicherheitslücken besteht darin, bei allen Texteingaben für eine korrekte Maskierung zu sorgen und alle anderen Eingaben auf ihren korrekten Datenyp zu überprüfen, so daß in Zahlfeldern keine Texte akzeptiert werden. Gespeicherte Prozeduren dürfen nicht per Stringverkettung ausgeführt werden, sondern die benötigten Parameter sind getrennt zu erstellen und zu belegen. Dasselbe Problem taucht auf, falls bsp. ein Sicherheitskonzept dadurch realisiert wird, daß Nutzer mit administrativen Aufgaben eigene Where-Fragmente in eine Tabelle eintragen und diese ungeprüft zu kompletten Sql-Anweisungen zusammengefügt werden. Schließlich wird am letzten Beispiel deutlich, wie eine Kombination von Sicherheitslücken (Sql-Injektionen und eine zu starke Verbindung) zu größeren Problemen, nämlich der Erstellung eines eigenen Admins, führen kann. Besitzt die genutzte Verbindung dagegen nur das Recht, gespeicherte Prozeduren auszuführen, so werden Delete-Aktionen auf den Tabellen verboten, ebenso ist in diesem Fall das Ausführen der sp_addlogin nicht möglich. Falls Leser solche Beispiele zum ersten Mal sehen: Keine Firewall oder die Nutzung von SSL schützt vor den Gefahren einer solcherart strukturierten Anwendung. Selbst einfache Suchmasken ohne eine Eingabefunktionalität können bei ungenügender Verarbeitung der Eingaben beliebige zusätzliche Befehle ausführen.

7. Eine Web-Datenbank mit manueller Teilreplikation oder die Nutzung einer direkten Lösung

Plant eine kleinere Firma ohne eigene IT-Mitarbeiter, Teile ihrer bislang lokal genutzten Datenbank auf der Firmenhomepage zu verwenden, so tauchen diverse Probleme auf. Zwar unterstützen heutzutage die meisten Provider mit Angeboten für Webseiten auch eine Datenbank-Lösung. Jedoch handelt es sich hierbei um beim Provider liegende, abgeschottete Systeme. Die Anbindung an die Homepage muß per Auftragsprogrammierung abgewickelt werden, da Provider im Regelfall nur rohe mySql-Systeme anbieten, auf welche mit PHP oder Perl zugegriffen wird. Da es sich damit um ein zweites System zusätzlich zur bsp. intern bereits genutzten Access-Datenbank handelt, müssen die Daten regelmäßig per Hand ein zweites Mal eingegeben und gepflegt werden. Ein automatisierter, etwa nächtlich durchgeführter Export in das externe System scheitert in der Regel an den Sicherheitsgrenzen, die vom Provider vorgegeben sind. Dasselbe gilt für die Rückrichtung, etwa kleine Bestellvorgänge, die auf der Domain per Formular eingetragen werden können. Da das eigene, manchmal von Firmenmitarbeitern entwickelte Access- oder FileMaker-System lokal funktioniert, werden Bestellungen per Mail entgegengenommen und ein zweites Mal in das interne System eingegeben. Die Lösung eines selbst betriebenen Webservers, der per Standleitung am Internet hängt, verbietet sich für eine kleinere Firma, da die Konfiguration eines solchen Systems einen unrealistisch hohen Mitarbeitereinsatz erfordert. Das Ergebnis ist, daß die eigentlich für Datenbanken charakteristische Redundanzfreiheit bei einem solchen System nicht mehr existiert. Und in jenem Maße, in welchem viele Kunden Bestellungen über die Domain abwickeln, verschärft sich dieses Problem.

Anstelle einer solchen manuellen Replikation stellt das Hauptprojekt Server-Daten: Die Web-Datenbank - Ihre einfache Online-Lösung eine Möglichkeit dar, einerseits die bislang intern genutzte Datenbank auf ein höheren Sicherheitsanforderungen genügendes DBMS zu verschieben und andererseits Teile der Datenbank in die Homepage so einzubinden, daß sowohl Lese- als auch Schreibzugriffe vom Web her möglich sind. Ferner ermöglicht es die Vergabe ausdifferenzierter Rechte und die Aktivierung einer Protokollierung, welche Zeitpunkt und Name des letzten Schreibzugriffes für jeden Datensatz protokolliert. Wird nur ein einziges System genutzt, auf welches von verschiedenen Seiten mit abgestuften Rechten zugegriffen wird, so entfällt die Notwendigkeit einer manuellen Replikation. Die oben genannten Kriterien einer dreischichtigen Anwendung, einer schwachen Verbindung zwischen Web- und Datenbankserver sowie einer abschirmenden Schicht gespeicherter Prozeduren mit der Möglichkeit, eigene Sicherheitsregeln zu definieren, erfüllt dieses System. Auch für die tabellen- und abfrageerzeugenden Zugriffe werden die Rechte der Verbindung nicht erhöht, sondern es wird das Verfahren verwendet, welches unter Sql-Befehl als SysAdmin beschrieben ist.

8. Literatur

Das Principle of least Privilege ist zum ersten Mal 1975 in dem Artikel The Protection of Information in Computer Systems von Jerome H. Saltzer und Michael D. Schroeder, Department of Electrical Engineering and Computer Science am Massachusetts Institute of Technology in Cambridge erwähnt worden. Es findet sich im ersten Abschnitt Basic Principles of Information Protection: 'Every program and every user of the system should operate using the least set of privileges necessary to complete the job. Primarily, this principle limits the damage that can result from an accident or error. It also reduces the number of potential interactions among privileged programs to the minimum for correct operation, so that unintentional, unwanted, or improper uses of privilege are less likely to occur. Thus, if a question arises related to misuse of a privilege, the number of programs that must be audited is minimized'.

Weitere Ausführungen waren bei IBM unter http://www-128.ibm.com/developerworks/linux/library/s-priv.html - Software security principles, bei Microsoft unter Security Tips: Defend Your Code with Top Ten Security Tips Every Developer Must Know zugänglich. Der IBM-Artikel spricht zusätzlich von 'Compartmentalization', der Abschottung der einzelnen Schichten gegeneinander, der Microsoft-Artikel enthält zusätzliche Beispiele zu Sql-Injections. Dreischichtige Architekturen werden unter dem Titel Three-Tiered Distribution näher beschrieben.

© 2003-2018 Jürgen Auer, Berlin.