Häufig werden Delphi-Programme zusammen mit zentralen Datenbanken eingesetzt. Allerdings ist die Verbindung zum Datenbankserver oftmals nicht richtig gesichert. Nicht selten sind leider auch rein client-seitig geschützte Anwendungen zu finden, die die Datenbank als reine Datenablage nutzen und das Sicherungspotential des Datenbankmanagementsystems brach liegen lassen. Ein weiteres Sicherheitsproblem sind nach außen hin geöffnete SQL-Datenbankserver (offene Ports) und SQL-Injects. In diesem Artikel gehen wir auf diese Sicherheitsaspekte ein und entwickeln eine geschützte Beispielanwendung.

Einleitung

Dieser Artikel richtet sich an all diejenigen Leser, die ihre Datenbankanwendungen ein wenig sicherer machen möchten. Eine absolute Sicherheit werden wir nicht erreichen, aber es wird gezeigt, wie man den täglichen Umgang mit Daten ein wenig sicherer macht.

Dieser Artikel richtet sich vor allem an fortgeschrittene Delphi-Entwickler, die bereits Erfahrungen im Umgang mit SQL-Datenbanken und Linux-Servern gemacht haben.

Um die folgenden Beispiele nachzubauen, benötigt man eine LAMP-Installation (wir verwenden Ubuntu 14.4 LTS mit LAMP-Konfiguration).

Weiters wird eine Delphi-Version benötigt. Wir werden die FireDAC-Komponenten verwenden, daher sollten diese auch in entsprechender Lizenz vorhanden sein (ggf. wird für den Remote-Zugriff ein AddOn-Pack benötigt). Für diesen Artikel kommt eine Trial von Delphi 10 Seattle zum Einsatz. Diese entspricht einer Architekt. Prinzipiell sind die gezeigten Verfahren aber auch mit anderen Komponenten wie z.B. ZEOS möglich.

Wir werden in diesem Artikel nicht alle Details beleuchten, die für die Umsetzung notwendig sind. Daher befindet sich am Ende des Artikels ein Download-Link zu einer ZIP-Datei in der ein Beispielprogramm, Konfigurationsdateien, SQL-Strukturen und ein PHP-Skript eingefügt sind.

Sichern des Datenbankzugriffs

Generell gibt man einen Datenbankserver niemals direkt im Netz frei. Bietet das DBMS (Datenbank-Management-System) eine verschlüsselte Übertragung, so wäre die im internen Netz noch akzeptabel, spätestens beim Internet ist davon aber dringend abzuraten. Datenbank-Management-Systeme sind spezialisiert auf Datenablage und -verwaltung. Eine gesicherte Übertragung derselben gehörte bei den meisten System nicht von Anfang an dazu, bei so manchen ist eine solche bis heute nicht nachgerüstet. Das hier verwendete MySQL bietet zwar die Möglichkeit, Daten per SSL zu übertragen, die Sicherung wird aber dennoch an diesem System demonstriert. Grund dafür ist erstens die immense Verbreitung von MySQL und zweitens, dass ein möglicher späterer Wechsel des DBMS in Punkto Sicherheit keine Überraschungen mehr mit sich bringt. Der dritte und wichtigste Grund ist aber, dass viele DBMS (wie eben z.B. MySQL) immer wieder kritische Sicherheitslücken aufweisen und daher ein nach außen lauschender SQL-Server ein nicht zu unterschätzendes Sicherheitsrisiko sein kann.

Zuerst einmal stellen wir sicher, dass der MySQL-Server nur lokal auf einen Port lauscht. Dazu loggen wir uns als root auf dem Server ein (oder schlüpfen mittels sudo su - in die root-Rolle). Dann bearbeiten wir die Konfigurationsdatei (hier /etc/mysql/my.cnf): In der Sektion [mysqld] ist die bind-address auf 127.0.0.1 zu konfigurieren.

Konfigurationsdatei von MySQL

Konfigurationsdatei von MySQL

Bei einer LAMP-Standard-Installation unter Ubuntu ist das bereits der Fall. Wer noch ein wenig mehr Sicherheit möchte, der ändert den Port vom Standard 3306 auf einen anderen Wert. Es ist darauf zu achten, dass man keinen Port eines anderen „Dienstes“ verwendet. Nach der Anpassung wird der MySQL-Server mittels service mysql restart neu gestartet, damit die Änderungen aktiv werden.

Nun benötigen wir noch einen Useraccount, über den wir eine SSH-Verbindung aufbauen können. Den User legen wir mittels adduser delphitage --shell /usr/sbin/nologin --no-create-home an.
Es wird ein User namens delphitage angelegt. Dieser hat kein Homeverzeichnis – dieses benötigt er auch nicht, da er nicht interaktiv mit dem Betriebssystem arbeiten soll. Damit er das auch auf keinen Fall tut, wird ihm keine Login-Shell zugewiesen.

Anlegen eines neuen Users mittels adduser

Anlage eines neuen Users

Es wird ein Passwort für den neuen Nutzer abgefragt. Das darf gerne völlig cryptisch sein, es wird ohnehin nie von einem Menschen eingegeben werden. Die weiteren Angaben, die zum Benutzer abgefragt werden, kann man einfach mit <ENTER> übergehen. Am Ende noch die Anlage des Users bestätigen, das war’s dann erstmal auf Linuxseite.
Nun müssen wir noch windowsseitig für die Verbindung sorgen. Hierzu verwenden wir das Kommandozeilenprogramm plink.exe (LINK). Dieses hört auf einen lokalen Port und leitet durch einen SSH-Tunnel an einen Server weiter. Es handelt sich um freie Software, die unter der MIT-Lizenz steht (ohne Gewähr). Mit folgendem Befehl bauen wir eine Verbindung auf:

plink.exe -N -L 13306:127.0.0.1:3306 delphitage@dtserver -pw delphitage -batch

Damit wird auf dem lokalen Rechner auf Port 13306 gehört und alles durch einen SSH-Tunnel auf den Server (dtserver) weitergeleitet. dtserver steht zum Beispiel für die IP-Adresse des Servers. Für den Verbindungsaufbau wird der zuvor angelegte User mit angegeben. Der Zielport der Weiterleitung wird aus Sicht des Servers angegeben, hier also auf dem localhost.

Das Ganze testen wir nun, indem wir uns mit der MySQL-Workbench an den lokalen Port 13306 hängen. Hierfür benötigen wir die Zugangsdaten des MySQL-Servers auf der Linux-Maschine.

Hier die Eintragungen für die connection:

MySQL-Workbench: Neue Verbindung

Formular für die Datenbankverbindung von MySQL-Workbench

Jetzt noch <Test Connection> gedrückt und es erscheint Folgendes:

Test erfolgreich

Test erfolgreich

Die Portweiterleitung durch den Tunnel funktioniert also. Sie bleibt solange bestehen, wie plink.exe läuft.

Schnell noch eine Datenbank anlegen. Wie man das nun macht ist Geschmackssache. Die gerade geöffnete MySQL-Workbench würde sich zwar anbieten, ich persönlich bevorzuge aber die MySQL-Shell auf dem Hostsystem. Also doch noch mal auf den Linuxrechner und dort am Prompt mysql -u root -p eingeben. Nach Eingabe des root-Passwords des Datenbankservers landet man in der MySQL-Shell.

Wir legen nun eine neue Datenbank, einen neuen User und eine erste Tabelle an:

create database delphitage;
create user delphitage identified by 'delphitage';
grant all on delphitage.* to delphitage;
use delphitage;
create table user_example(id integer primary key auto_increment, name varchar(30) not null unique key, username varchar(30) not null unique key, password varchar(30)not null);

Nun muss die Verbindung noch in ein Programm verpackt werden. Starten wir also Delphi und legen eine neue VCL-Anwendung an. Als Zielplatform wählen wir Win32. Dann wird ein neues Datenmodul angelegt.

Aufbau des Delphi-Projektes

Aufbau des Delphi-Projektes

Dem Datenmodul spendieren wir zwei Methoden (ssh_connect und ssh_disconnect) sowie eine private Variable, die die Prozess-ID der von uns gestarteten plink.exe aufnimmt. Die Variable belegen wir im onCreate des Datenmoduls mit 0 vor.

unit data;
...
type

TDaten = class(TDataModule)
procedure DataModuleCreate(Sender: TObject);
private
fProcessID: Cardinal;
fFilePath: String;
public
function ssh_connect: Boolean;
function ssh_disconnect: Boolean;
end;
...

procedure TDaten.DataModuleCreate(Sender: TObject);
begin
fProcessID := 0;
fFilePath := ExtractFilePath(ParamStr(0));
end;

function TDaten.ssh_connect: Boolean;
begin
if fProcessID=0 then
executeFile('plink.exe', '-N -L 13306:127.0.0.1:3306 delphitage@dtserver -pw delphitage -batch', fFilePath, fProcessID, false, false);
Result := fProcessID>0;
end;

function TDaten.ssh_disconnect: Boolean;
begin
if (fProcessID>0 and stopTask(fprocessID)) then
fProcessID := 0;
Result := fProcessID=0;
end;

Alle nicht erläuterten Hilfsfunktionen findet man im Beispielcode (Link am Ende des Artikels).

Die Parameter des plink-Aufrufes sind die selben wie zuvor. Wir generieren einen neuen Prozess für die plink.exe und verstecken diesen vor dem User (dieses erledigt die Hilfsfunktion executeFile() aus dem Beispielcode). Um den Prozess auch wieder beenden zu können, wird die Prozess-ID gespeichert. Im ssh_disconnect wird dann der Prozess mit der gespeicherten ID beendet.

Als Nächstes ziehen wir eine TFDConnection auf das Modul. Als DriverName wird MySQLgewählt. in den Params sind nun database, username, password und port einzutragen. In diesem Beispiel verwenden wir für die ersten drei Params delphitage. Das sollte man in der Praxis natürlich nicht tun. Für port geben wir denjenigen Port an, der auf den Server umgeleitet wird, in diesem Fall also 13306. Im BeforeConnect und AfterDisconnect rufen wir ssh_connect bzw. ssh_disconnect auf.

Weiters wird ein TFDPhysMySQLDriverLink benötigt. Wir legen ihn auf das Datenmodul, eine weitere Konfiguration ist nicht notwendig. Um überhaupt Daten zu sehen zu bekommen, legen wir noch eine TFDTable auf das Datenmodul. name und tablename setzen wir auf roles. Als Connection wird automatisch die bereits auf dem Modul liegende TFDConnection übernommen. Weiters legen wir eine Datasource auf das Datenmodul, welche wir mit der Table verbinden und ds_roles nennen. Auf unser Hauptformular legen wir ein TDBGrid und einen DBNavigator und verbinden beides mit der Datasource (nicht vergessen, das Datenmodul in die uses aufzunehmen).

Im OnShow der Form bauen wir Folgendes ein:

data.con.connected := True;
data.roles.Active := True;

Vor dem ersten Programmstart nicht vergessen, die libmysql.dll und plink.exein das Projektausgabeverzeichnis zu legen.
Nach einem beherzten <F9> sieht man Folgendes:

erster Programmstart

Erster Programmstart

Geben wir nun ein paar Datensätze ein, die ID lassen wir dabei außen vor. Nach Beenden und Neustarten des Programmes sehen wir:

zweiter Programmstart

Nun mit ein paar Daten

Das hat offenbar funktioniert, wir haben nun die ersten Daten über eine sichere Verbindung in die Datenbank geschrieben und auch wieder abgerufen.

Widmen wir uns also dem nächsten Punkt:

Zugriff auf erlaubte Daten und NUR auf diese!

Häufig findet man nur einen einzigen Benutzer für eine Datenbank vor. Der darf dann einfach alles, schlimmstenfalls ist es sogar der Master-User des ganzen DBMS. Die ganze Sicherheit liegt dann auf der Clientseite, also dem Anwendungsprogramm. Nach dem Grund für diese in meinen Augen ziemlich ignorante Handhabung befragt, antworten Entwickler oftmals:

Das Rechtesystem der Datenbank ist für unsere Zwecke nicht ausreichend, deshalb machen wir das gleich komplett selber!

Das Manko, mit dem die meisten Entwickler hier zu kämpfen haben, ist der Schutz des einzelnen Datensatzes. In den meisten Systemen lassen sich die Daten tabellenweise und spaltenweise schützen aber nicht zeilenweise. Wobei dies über einen gewissen Aufwand und intensive Verwendung von Views und Stored Procedures durchaus auch möglich ist. Leider ist das vielen zu aufwändig. Es werden dann einfach alle Daten zum Client übertragen und der entscheidet, was der User zu sehen bekommt oder ändern darf. Jeder, der die Client-Anwendung in die Finger bekommt, kann daher mit ein paar einfachen „Hacks“ Vollzugriff auf alle Daten erlangen. Zudem sollte man gerade in der heutigen mobilen Zeit mit dem übertragenen Datenvolumen sparsam umgehen.

Wenn man also schon sein eigenes Rechtesystem aufsetzt und dies erst auf dem Client greift, sollte man die Möglichkeiten des DBMS mitnutzen.

Die Idee ist einfach: Für jede Benutzer-„Rolle“ (z.B. Admin oder Redakteur) wird ein Datenbank-User angelegt, der über die gewünschten Rechte verfügt.
Dann sorgt man dafür, dass sich die Clientanwendung über diese DB-User an das DBMS anmeldet. Dies erreichen wir, indem wir uns die Anmeldedaten für den jeweiligen User erst einmal aus der Datenbank holen. Ähh, wie jetzt? Wir sollen die Anmeldedaten aus der Datenbank holen? Dazu müssen wir uns doch erstmal anmelden ….

Richtig! Um dies zu erreichen, benötigen wir eine Zwei-Phasen-Anmeldung. In der ersten Phase melden wir uns mit einem User (Erstanmelde-User) bei der DB an, der ausschließlich lesenden Zugriff auf eine Tabelle hat, in der der Programm-Username, der DB-Username und das DB-Password stehen. Es wird dann der entsprechende DB-Zugang auf Basis des Programm-Usernamens ermittelt und sich dann erneut bei der Datenbank angemeldet. Wenn das DBMS Stored Procedures bietet, wäre das eine noch wesentlich bessere Möglichkeit. Dann gibt man dem Erstanmelde-User nur das Recht, eine einzige Stored Procedure auszuführen. Dieser werden dann Programm-Username und Password übergeben und es werden DB-User und DB-Password zurückgegeben.

Beispiel: Meine Username/Passwort – Kombination ist paul/passP. Die Client-Anwendung meldet sich mit einem festen Nutzer erstanmelder/pass1 beim DBMS an. Dieser „erstanmelder“-Nutzer hat nur das Recht, eine Stored Procedure getDBUser(myUsername, myPassword) aufzurufen. Dieser übergibt er paul/passP, woraufhin in einer Tabelle der passende DB-User mit den gewünschten Rechten zurückgegeben wird, z.B. Redakteur/passR. Die Verbindung wird nun getrennt und der Client meldet sich mit Redakteur/passR wieder beim DBMS an. Dadurch hat er nun genau die gewünschten (Rollen-) Rechte eines Redakteurs.

Jetzt haben wir schon wieder ein wenig mehr Sicherheit, aber leider immer noch hart kodierte DB- und SSH-Zugangdaten im Kompilat. Dadurch wird ein simples Prinzip verletzt:

Ein Angreifer sollte dadurch, dass er die Client-Anwendung besitzt, keinerlei Vorteil haben.

Und den hätte er. Denn dadurch, dass er SSH- oder MySQL-Zugangsdaten besitzt (wenn auch nicht mit den richtigen Rechten) könnte er Sicherheitslücken des DBMS ausnutzen.

Schöner wäre:

Keine Zugangsdaten in der Exe

Das können wir erreichen, indem wir die Zugangsdaten in Phase eins nicht selbst aus der Datenbank abrufen, sondern von einem Apache-Server abfragen: dies gilt dann gleichermaßen für die SSH- und DB-Zugangsdaten. Hierzu übergeben wir in einem HTTPs-Request username und password, die der User eingibt an ein PHP-Script auf dem Server. Dieses liefert uns dann die SSH- und DB-Zugangsdaten zurück. Wie anfangs erwähnt, braucht man eine LAMP-Installation, um diesen Artikel nachvollziehen zu können. Nun kommen auch das A und das P zum Einsatz.

Zwei-Phasen-Verbindungsaufbau zum DBMS mittels HTTPs und SSH-Tunnel

Zwei-Phasen-Verbindungsaufbau zum DBMS mittels HTTPs und SSH-Tunnel

Zertifikate

Um eine HTTPs-Verbindung aufbauen zu können benötigen wir Zertifikate. Ein Webseitenzertifikat (bzw. das Zertifikat eines „Servers“) enthält die Identitätsdaten des Servers und kann dazu benutzt werden, bei einer Kommunikation die Echtheit des Servers zu prüfen, um eine Man-In-The-Middle-Attacke zu verhindern. Nun kann man ein solches Zertifikat von einer oder mehreren Stellen mit deren öffentlichem Schlüssel verschlüsseln lassen und so die Echtheit der Informationen garantieren. Dies nennt man „signieren“ . Die Webseitenzertifikate werden von vertrauten Stellen, sogennanten Zertizierungsstellen (Certificate Authority, kurz CA), wie z.B. der Deutschen Telekom, signiert und deren öffentliche Schlüssel werden mit den meisten Browsern mitgeliefert.

In unserem Fall können wir unser Zertifikat selber signieren, denn wir vertrauen uns schließlich selbst. Wir werden alle nötigen Schlüssel mittels OpenSSL selbst erzeugen. OpenSSL ist in LAMP-Installationen meist vorinstalliert. Ansonsten kann es über die entsprechende Paketverwaltung nachinstalliert werden (bei Ubuntu: apt-get install openssl).

Selbst zertifizierte CA

Zuerst einmal erstellen wir uns eine eigene Zertifizierungsstelle. Dazu erzeugen wir erst einmal einen geheimen Schlüssel:

Erstellung geheimer Schlüssel

Erstellung geheimer Schlüssel

Das eingegebene Kennwort ist gut aufzubewahren. Ohne dieses können keine Zertifikate signiert werden.
Erstellen wir nun das Root-Zertifikat unserer CA:

Erstellung CA-Zertifikat

Erstellung des CA-Zertifikats

Die Zertifizierungsstelle ist nun für 1024 Tage gültig. Es werden vor der Generierung des Zertifikates einige Daten abgefragt. Unter anderem wird ein Passwort benötigt. Hiermit ist das Passwort gemeint, das wir zur Erstellung des geheimen Schlüssels verwendet haben. Alle Fragen sollten korrekt beantwortet werden, denn die Informationen sind öffentlich sichtbar.

Server-Zertifikat erstellen

Nun benötigen wir noch ein Serverzertifikat, welches der Apache zur Verschlüsselung und zur Identifikation verwenden kann. Wir erstellen uns als erstes einen privaten Schlüssel. Auf diesem aufbauend erstellen wir einen Zertifikatsrequest. Aus diesem wird dann ein Zertifikat erzeugt, welches wir mit dem geheimen Schlüssel der CA unterschreiben. Den Zertifikatsrequest benötigen wir danach nicht mehr, er kann entsorgt werden.

erstellung_seervercert

Erstellung des Server-Zertifikats

Den privaten Schlüssel, das erhaltene Serverzertifikat und das CA-Zertifikat stellen wir dem Apache zur Verfügung. Wir hinterlegen dies alles im Verzeichnis /home/ssl/dtserver. Der Ablageort ist frei wählbar, die Dateien müssen nur für den Apache erreichbar sein (Rechte).

Apache Konfiguration

Nun müssen wir dem Apache ggf. noch beibringen, überhaupt mit SSL umgehen zu können. Dazu aktivieren wir das Modul mod_ssl mittels a2enmod ssl. Sollte das Modul bereits aktiviert gewesen sein, so werden wir darüber informiert. Aktiv wird das Modul erst nach dem Neuladen der Apache-Konfiguration. Das machen wir später, zuvor legen wir noch eine neue Website an. Diese wird einzig ein PHP-Script enthalten, das für unsere Authentifizierung zuständig ist.
Dazu erstellen wir einen virtuellen Host. Die Informationen dazu legen wir in einer Datei namens dtserver.conf ab. Diese wird in das Verzeichnis für verfügbare Webseiten des Apaches gelegt.

So sieht unsere Konfiguration aus:

<VirtualHost dtserver:443>
ServerName dtserver

ServerAdmin webmaster@delphimagazin.de
DocumentRoot /home/www/dtserver

SSLEngine ON
SSLCertificateFile /home/ssl/dtserver/zertifikat-pub.pem
SSLCertificateKeyFile /home/ssl/dtserver/zertifikat-key.pem
SSLCACertificateFile /home/ssl/dtserver/ca-root.pem
<Directory /home/www/dtserver/>
Options -Indexes
</Directory>

LogLevel debug

ErrorLog /var/log/apache2/error_dtserver
CustomLog "/var/log/apache2/access_dtserver" combined
</VirtualHost>

Um unsere Konfigurationen zu aktivieren, veranlassen wir den Apache dazu, seine Konfigurationsdateien neu zu lesen: service apache2 reload.

Jetzt ist unser Apache konfiguriert. Damit er uns auch von Nutzen ist, müssen wir noch ein kleines PHP-Script im DocumentRoot ablegen.
Dieses erhält per HTTP-POST einen Usernamen und ein Passwort. Diese Daten verifiziert es in der Datenbank und liefert die Anmeldedaten für den SSH-Tunnel und die Datenbankverbindung aus den entsprechenden Tabellen der Datenbank zurück. Wir nennen es index.php:

PHP-Script

PHP-Script: index.php

Dabei ist besonders zu beachten, dass wir die per POST an das PHP-Skript gesendeten Daten nicht direkt in das SQL-Statement einbauen, da ein Angreifer ansonsten per SQL-Inject in unsere Datenbank eindringen könnte. Mehr dazu siehe z.B. hier.

Die zugehörigen Tabellen müssen natürlich auch angelegt werden.

Tabellen für die Anmeldung

Tabellen für die Anmeldung

Wir haben hier zwei Tabellen vorliegen. In der Tabelle role sind die einzelnen Benutzerrollen definiert. Für diese sind die Anmeldedaten für die Datenbank hinterlegt. Die Tabelle user enthält die Anmeldedaten der User für die Anwendung. Über die role_id wird die entsprechende Rolle identifiziert. Dieser Schritt ist notwendig, da eine Rolle mehreren Usern zugeteilt werden kann.

Nun sind wir wieder einmal auf der Linuxseite fertig. Bevor wir uns unserem Delphi-Programm widmen, kopieren wir noch das CA-Zertifikat vom Linuxserver in das Ausgabeverzeichnis unserer Anwendung. Desweiteren kopieren wir die Dateien libeay32.dll und ssleay32.dll aus dem OpenSSL-Projekt dorthin. Diese DLLs sind in den jeweiligen OpenSSL-Archiven auf http://indy.fulgan.com/SSL/ zu finden.

Weiter geht es in der IDE:

Verbindung über Indy

Wir ziehen eine IdHTTP-Komponente und eine IdSSLIOHandlerSocketOpenSSL-Komponente auf das Datenmodul. Im IdHTTP tragen wir die zweite Komponente als IO-Handler ein.

Im IO-Handler setzen wir in den SSL-Options die VerifyDepth auf 1. Hiermit wird angegeben, dass nur direkt von unserer CA ausgestellte Zertifikate akzeptiert werden. Wir lassen SSL V1, V2 und V3 zu. Im VerifyMode aktivieren wir sslvrfFailIfNoPeerCert. Dadurch werden nur Zertifikate von bekannten CAs anerkannt. Die gewünschte Zertifizierungsstelle muss über den Parameter RootCertFile bekannt gemacht werden. Das machen wir nicht in der Komponente sondern im onCreate unseres Datenmoduls:
fFilePath := ExtractFilePath(ParamStr(0));
SSHHandler.SSLOptions.RootCertFile := fFilePath + 'ca-root.pem';
Grund hierfür ist, dass unser Code portabel bleibt. Das benötigte Zertifikat muss lediglich im gleichen Verzeichnis liegen, wie die EXE.

Einstellung der SSL-Optionen

Einstellung der SSL-Optionen

Leider beherrschen die Indys noch keine Server Name Indication Diese wird benötigt, wenn ein Apache mehrere unterschiedliche SSL-Seiten auf der selben IP hostet. Wir helfen deshalb hier mit einem etwas unsauberen Hack nach und implementieren die Ereignismethode procedure OnSSLStatusInfoEx wie folgt:

begin
SSL_set_tlsext_host_name(AsslSocket, 'dtserver');
end;

Dadurch wird wird bereits im Header mit übertragen, an welchen Virtual-Host die Anfrage gehen soll. Somit kann der Apache dann die richtigen Zertifikate anziehen.

In dem Beispielprogramm haben wir nun die Anmeldedaten für die Datenbank und den SSH-Tunnel vom Webserver geholt.

Damit haben wir alle Komponenten einer sicheren Datenbank-Lösung zusammen.

Fazit & Ausblick

In diesem Artikel haben wir eine zwar nicht einfach zu verstehende, aber dennoch einfach zu implementierende Sicherheits-Architektur zur Datenbank-Verbindung vorgestellt. Das entwickelte Beispielprogramm enthält bereits alle Teile eines User- und Rollen-Systems, dass über die folgenden Vorteile verfügt:

  • Alle Verbindungen sind verschlüsselt.
  • Es befinden sich keine Zugangsdaten in der Exe, d.h. ein Angreifer hat keine Mehr-Informationen (oder bessere Chancen) dadurch, dass er den Client „in die Finger bekommt“.
  • Die Echtheit des Servers wird mittels CA-Zertifikat überprüft, so dass Man-In-The-Middle-Attacken abgewehrt werden können.
  • Auschließlich Programme, die für den Internet-Datenverkehr geeignet sind werden auch zum Internet hin geöffnet (SSH und Apache). Datenbank-Sicherheitslücken können nur sehr schwer ausgenutzt werden.
  • Die Lösung ist auf andere Datenbanken portierbar.
  • Es können leicht mehrere Server als Authentifizierungs-Cluster eingesetzt werden. Dadurch kann z.B. der Apache und SSH auf einem Linux-System liegen, der Datenbankserver aber ein (Windows) MS-SQL-Server sein.

Unsere Lösung hat dennoch einen Schönheitsfehler: Zeilen in SQL-Tabellen werden weiterhin nicht durch das DBMS-User-System geschützt, sondern nur durch die Client-Anwendung.

Konfiguriert man jetzt noch den Apache so, dass er Clientzertifikate verlangt, kann man sich darüber eine schöne Lizenzierung aufbauen.

Dies alles wird gegebenenfalls in einem zukünftigen Artikel behandelt werden.

Links

Download: ZIP-Datei mit Beispielprogramm, Konfigurationsdateien, SQL-Strukturen und PHP-Skript

Links aus dem Artikel:

Sonstige Links:

  • Um sich per SSH zu einem Server zu verbinden, kann man MobaXterm sehr gut gebrauchen.

Workshops, Beratung oder Umsetzung?

Wir bieten umfangreiche Workshops, Beratung und Umsetzung unter anderem im Themenbereich „Sichere Datenbankverbindungen“ an.

Kommentare sind deaktiviert.