# Wie speichere ich das DB Passwort richtig ab?



## kaffeeliebhaber (2. Okt 2020)

Hallo liebe Community,

dies ist mein erster Thread nach Jahren, also bitte seht es mir nach, wenn nicht alles perfekt beschrieben ist. Bin aber für Verbesserungen natürlich offen.

*Kurze Beschreibung zur Geschichte*
Ich programmiere als Hobby sehr gerne mit Java und bin gerade dabei, mir JavaFX und MySQL in Kombination anzuschauen. Ich habe viele Tutorials angesehen, in denen thematisiert wurde, wie genau man eine Verbindung zu einer Datenbank herstellt. In meinem Fall einer MySQL Datenbank. In diesen einfachen Beispielen wird immer der Benutzername und Passwort (als Klartext) eingegeben um sich mit der Datenbank zu verbinden (in einer kleinen Java-Applikation zur Demonstration). 

Soweit ist mir alles klar und funktioniert auch alles super.

*Nun zu meinem aktuell "Problem"*
Mir stellt sich jedoch die Frage, wie genau ich das Password in oder durch meine Applikation speichern soll. 

*Denn*
In meinem aktuell recht einfach gehaltenen Applikations-Prototypen kann man bisher sowohl den Typ der Datenbank, den Connection-String, als auch Benutzername und Password für die Datenbank hinterlegen. Diese speichere in aktuell in einer *.json Datei ab (nur als Beispiel). Das Password in dieser *.json Datei als Klartext abzuspeichern wäre natürlich nicht ideale Weg. Somit würde ich ihn gerne gehasht (oder welches Verfahren man dafür benutzt) abspeichern. Doch wie löse ich den Hash  auf, wenn ich mich doch mit dem Klar-Password gegen die Datenbank authentifizieren muss. Denn ich verstehe es so, dass es unmöglich (zumindest beinahe) ist, einen Hash aufzulösen. Und würde ich ein kryptographischer Verfahren nehmen, müsste ich zumindest das verschlüsselte Password und den passenden Schlüssel abspeichern. Doch auch das scheint mir nicht der passende Weg zu sein. Deswegen hoffe ich auf euer Wissen und ggf. passende Vorschläge. 

Sicherlich gibt es dafür einen guten Weg, dies in einer Applikation zu implementieren, aber mir fehlt zum einen der technische Background (Thema Sicherheit und Verschlüsselung) und zum anderen die Schlagwörter, mit denen ich google befragen und eventuell Antworten erhalten könnte

Ich hoffe, ihr versteht mein Problem. Ansonsten schreibt es mir gerne und ich versuche passendere Wort dafür zu finden.

Ich danke schon einmal jedem, der sich diesen wirren Text durchliest.


----------



## Thallius (2. Okt 2020)

Ganz einfach: Es geht nicht. Das ist der Grund warum man eine Datenbank immer über einen Webservice anspricht. In diesen kannst du dann einen Login implementieren und dort muss sich der User halt erst mit seinem Passwort anmelden bevor er irgendwelche Daten kriegt.


----------



## mihe7 (3. Okt 2020)

@kaffeeliebhaber Je nachdem, um welche Art von Anwendung es geht, könntest Du die Login-Daten verwenden, um damit die Verbindungsdaten zu verschlüsseln. Natürlich muss beim Ändern der Login-Daten dann auch neu verschlüsselt werden.


----------



## kaffeeliebhaber (3. Okt 2020)

Zunächst einmal vielen Dank an euch beide für das durchlesen meiner Frage und dank an dich mihe7 für deine Antwort.

Die Antwort liest sich sehr einfach, nur so richtig verstehen tue ich sie leider nicht. Bitte verzeih mir.

Ich weiß ehrlich gesagt nicht, was du mit *Login-Daten* meinst?

Aktuell steht in meinem Quellcode 

```
username = 'root'
password = 'pw'
```

Das sind die Anmeldedaten für den MySQL Server.

Nun möchte ich jedoch die Daten nicht fest im Quellcode stehen haben, sondern über die UI einstellbar und irgendwo abspeichern. Und das verschlüsselt. Mir stellt sich dann nur die Frage, wie ich aus den verschlüsselten Daten wieder das eigentliche Passwort erhalten kann, sofern das überhaupt möglich ist.

Meine Idee dabei ist, dass über das UI einstellbar sein soll, welche Art von DB, MySQL oder MS SQL, hinter der Anwendung liegt und mit welchen Daten er sich gegen die DB authorisiert.

Hast du für deine obige Antwort vielleicht ein kurzes Beispiel, was deine Antwort illustriert? Ich wäre dir wirklich zu Dank verpflichtet.


----------



## kaffeeliebhaber (3. Okt 2020)

PS: Natürlich auch Dank an dich Thallius. Hatte das nur in meiner obigen Antwort vergessen zu erwähnen.

Ich bin in der Thematik (WebService und Datenbank) leider nicht ganz vertraut. Ist das wirklich der normale Prozess, das Ganze so abzubilden? Falls ja, müsste ich mir dazu vielleicht mal einen Artikel oder Beitrag dazu durchlesen, wie genau man das Ganze aufzieht.

Dürfte ich dich fragen, ob du dazu vielleicht eine gute Quelle hast? Andernfalls konsultiere ich unseren guten Freund google.


----------



## mihe7 (3. Okt 2020)

Ah, korrigiere mich, wenn ich falsch liege:

1. Es geht um eine klassische Client/Server-Anwendung, wobei die DB im lokalen Netz (ggf. sogar auf dem Arbeitsplatz selbst) läuft.
2. Der Benutzer kann sich gar nicht an der Anwendung anmelden.

Richtig, so?


----------



## kneitzel (3. Okt 2020)

Die Frage ist erst einmal, um was für eine Umgebung es hier geht.

Generell ist der Schutz des Passwortes extrem schwer, denn der Client muss es lesen können. Daher hat ein Benutzer, der Zugriff auf den Rechner hat, immer die Möglichkeit, das Passwort auch auszulesen. Angriffsvektoren sind hier fast beliebig ausdenkbar.

Daher ist eine Lösung: gar kein Passwort speichern. Dies ist z.B. möglich in Windows Domänen mit Windows Integrated Authentication wie es z.B. der MS SQL Server unterstützt. Der User meldet sich dann am Rechner an mit seiner Domain Kennung an und diese Authentifizierung wird dann auch weiter genutzt.

Das nächste, was mir (unter Windows!) einfällt: Credential Manager - Windos hat eine Passwort Verwaltung eingebaut und diese kann man natürlich auch nutzen. Ist aber native von Java aus nicht verwendbar. Da wäre ggf. https://github.com/dariusz-szczepaniak/java.jna.WindowsCredentialManager eine Überlegung wert. 

Das waren erst einmal "Windows only" Überlegungen. Wenn man eine Java Anwendung schreibt, dann wird man aber ggf. die Plattform Unabhängigkeit nicht einfach so wegwerfen. Aber diese Optionen wollte ich zumindest nennen, denn dieser "Windows Domänen Fall" ist bei Client/Server Anwendungen nicht so unüblich. Außerhalb würde ich auch definitiv NIE ein solches Szenario verwenden. Den Datenbank-Zugriff gebe ich nur in gesicherten Netzen nach außen! Ansonsten wäre generell die Empfehlung, einen Service zu schreiben, der die Schnittstelle nach außen darstellt. Ein Web Service wäre hier sozusagen mein Lösungsvorschlag. (Diese Fälle gibt es aber natürlich auch in nicht Windows Netzen - ganz klar.)

Aber zurück zum Thema: Datenbankverbindung und eine Verschlüsselung des Passwortes wird gesucht. Da wäre mein erster Gedanke dann:


			Jasypt: Java simplified encryption - Jasypt: Java simplified encryption - Main
		

jasypt unterstützt auch Hibernate, Spring, ... so dass es relativ universell und einfach integrierbar ist. Aber die Security Probleme bezüglich Nutzer mit lokalem Zugriff bleiben natürlich weiter bestehen und werden auch von jasypt nicht gelöst!


----------



## kaffeeliebhaber (3. Okt 2020)

Schönen guten Morgen zusammen.

*Danke*
Wie immer zu Beginn, möchte ich mich wieder einmal bei euch für eure Beiträge bedanken. Ihr helft mir sehr, mein gefüllt nur im Kopf existentes Problem, zu lösen. Vielleicht. 

*Thema*
Im Prinzip, so denke ich zumindest, ist es eine klassische Client / Server Anwendung. Dein Punkt 1 @mihe7 trifft es genau. Richtig formuliert.

Zu deinem Punkt 2 musste ich etwas nachdenken, da es meine Sicht der Benutzer in meinem kleinen Hobby-Projekts noch einmal hinterfragt.
Ziel wäre es für mich:

*User: Admin*
1. Login - Screen ( Username & Passwort)
2. Er kann in die Einstellungen und dort die DB hinterlegen. (Typ, Connection-String, Username und Passwort)

*User: Anwender*
1. Login - Screen (Username & Passwort)
2. Verifiziert sich mit dem Username & Passwort (das PW ist natürlich verschlüsselt auf der DB abgespeichert).
Natürlich nur, wenn der Admin vorher die DB richtig konfiguriert hat, sodass sich der Benutzer richtig angemeldet hat.


----------



## kneitzel (3. Okt 2020)

Also geht es nicht darum, dass ein Passwort z.B. für den Zugriff auf die Datenbank gespeichert werden soll, sondern Du willst User authentifizieren.

Da ist es üblich, nicht das Passwort selbst zu speichern sondern lediglich einen Hash, der berechnet wurde. Damit das nicht zurück verfolgt werden kann, wird noch ein Seed verwendet.
Bei der Authentifizierung berechnest Du aus dem eingegebenen Passwort wieder den Hash und vergleichst das Ergebnis mit dem gespeicherten.

Das wäre so das übliche Vorgehen, welches z.B. auch unter https://auth0.com/blog/adding-salt-to-hashing-a-better-way-to-store-passwords/ ausführlicher erläutert wird.

Bezüglich Java Code habe ich gefunden: https://howtodoinjava.com/java/java...password-hash-md5-sha-pbkdf2-bcrypt-examples/. Aber das MD5 als erste, einfachste Variante vergisst Du gleich - das gilt als unsicher und überholt und es gibt keinen Grund, das zu nutzen, denn die sicheren Möglichkeiten werden ja auch direkt genannt ....


----------



## kaffeeliebhaber (3. Okt 2020)

Doch, es geht genau um den ersten Teil deines ersten Satzes @JustNobody 



> Also geht es nicht darum, dass ein Passwort z.B. für den Zugriff auf die Datenbank gespeichert...


----------



## kaffeeliebhaber (3. Okt 2020)

Wenn ich einen normalen Benutzer, den ich in der DB in einer Tabelle, z.B. User, anlege, authorisieren möchte, geht dabei ohne Probleme. Ich lege dazu einfach seinen Benutzernamen an und speichere sein Passwort gehasht in der Tabelle ab. Wenn er sich nun einloggen möchte, hashe ich sein eingegebene Passwort und vergleiche es mit dem in der DB zu seinem Usernamen gehörigen. Wenn beide Passwörter gleich sind, ist der Login erfolgreich. Sehr einfach ausgedrückt.

Es geht aber darum das Passwort für die DB irgendwie zu hinterlegen. Am liebsten auch als Hash-Wert. Doch mit diesem Hash-Wert kann ich mich eben nicht an der DB einloggen, da es eben nicht das eigentliche Passwort der DB ist. 

Ich drücke mich wohl nicht ganz präzise aus.


----------



## LimDul (3. Okt 2020)

Vielleicht mal eine ganz wichtige Frage
* Darf der User der Anwendung das Datenbank-Passwort kennen?

*Ja*
Dann leg das Passwort entweder im Klartext in einer Textdatei ab oder besser mit einem symmetrischen Schlüssel geschützt in einer Textdatei . Der Schlüssel ist im Programmcode einkompiliert. 

Folgen:
* Der User kann sich mit einem normalen DB-Client auf die Datenbank verbinden und den gesamten Inhalt lesen und, sofern der DB User auch Schreibrechte hat, ändern.

*Nein*
In dem Fall muss man schauen, ob die DB wie von @JustNobody beschrieben ein alternatives Anmeldeverfahren hat oder einen Webservice dazwischenschalten, der nur die Operationen auf der Datenbank erlaubt, die für den Nutzer der Anwendung sinnvoll sind. Eine normale Verbindung mit Passwort zur Datenbank bekommt man nicht abgesichert, das Passwort kann von technisch versierten Usern immer ausgelesen werden.


----------



## kneitzel (3. Okt 2020)

Also das Passwort für die Datenbank verschlüsselt ablegen: jasypt deckt dies gut ab. Wenn man diese Library nicht nutzen will, kann man schauen, was die prinzipiell gemacht haben - da werden halt die Mittel des Java Frameworks bzw. von Crypto Providern benutzt. Es findet sich da also keine eigene Cryptographie in der Library sondern es geht um das Drumherum.

Aber: das ist alles nicht wirklich sicher! An das Passwort kommt man problemlos ran!

Ebenso das Datenbank und Client auf einem System / eigene User Authentifizierung: das ist so unüblich. Auf dem Client hat man ja bereits eine Authentifizierung... ich bin an meinem System angemeldet. Und ich habe Admi. rechte oder eben nicht ... Da macht es wenig Sinn, da noch etwas anderes zu implementieren....

Wieso macht das keinen Sinn? Der User hat weitgehende Rechte auf dem System. Also z.B. MySQL - wenn ich da an den Server nicht ran komme, weil ich das Passwort vergessen habe oder so: es finden sich zig Anleitungen, wie ich da wieder dran komme. Also eine Sicherheit gibt es nicht....


----------



## mihe7 (3. Okt 2020)

EDIT: Achtung, Beitrag hat sich mit @LimDul und @JustNobody überschnitten.

Nächste Frage: vor _wem_ soll das DB-Passwort geschützt werden? Geht es nur darum, neugierige Blicke der  Anwender zu verhindern? Dann kannst Du im Prinzip das Passwort mit einem festen Schlüssel und popligster XOR-Verschlüsselung ablegen.

Natürlich kannst Du auch das Betriebssystem bemühen, d. h. Passwort im Klartext speichern, die Anwendung unter einem anderen User laufen lassen und dafür sorgen, dass nur dieser Benutzer Zugriff auf die Daten erhält.

Wenn Du dann sagst: ok, ich will aber noch höhere Sicherheit (die Datei könnte ja in fremde Hände fallen), dann kannst Du Kryptographie einsetzen. Als Passwort kannst Du ein Anwendungspasswort verwenden, das der Admin vergibt und vom User eingegeben werden muss. Außerdem kannst Du - in der Entwicklung komplizierter, für den Anwender einfacher - mit den Passwörtern der Benutzer arbeiten.

Beispiel: beim ersten Aufruf der Anwendung legt der Admin sein Passwort fest. Die Konfigurationsdatei wird mit einem zufälligen Schlüssel und z. B. AES-256 verschlüsselt. Der zufällige Schlüssel wird nun für jeden Benutzer, verschlüsselt mit seinem Passwort, abgelegt. Wird das Passwort geändert, muss natürlich neu verschlüsselt werden.

Die beste Lösung ist aber immer, keine Passwörter zu speichern. Das kannst Du z. B. über die DB erreichen. In der Konfigurationsdatei stehen dann z. B. Host und DB, die Benutzerverwaltung erfolgt dagegen direkt über das DBMS. Benutzer der Anwendung = DB-Benutzer.

Willst Du den Zugriff auf die Daten noch etwas schützen, kannst Du das z. B. mit Rechten erreichen. Zum Beispiel gibt es in manchen Unternehmen "Freaks", die gerne mittels Excel Auswertungen fahren möchten. Für die gibt es dann einen extra DB-User, der nur lesend auf bestimmte Tabellen bzw. extra eingerichtete Views zugreifen kann.

Die ultimative Lösung ist natürlich ein Service, der die DB kapselt, wie die anderen ja schon geschrieben haben.


----------



## kneitzel (3. Okt 2020)

Und wenn es um eine Autorisierung an Fremdsystemen geht: hier ist auch generell die Frage: muss es etwas eigenes sein? Was fehlt dir an vorhandenen Lösungen?

- man kann existierende Identity Provider nehmen. Im öffentlichen Bereich finden sich da viele Anbieter: Facebook, Google, Microsoft, Apple, ....
- es gibt genug (teilweise freie) Software, die da was bieten. Angefangen von dem ‚alten‘ LDAP / AD Anbietern hin zu aktuellen OAUTH Lösungen.

Das Ganze hat dann diverse Vorteile:
- ggf können User vorhandene Accounts verwenden. (Ich freue mich immer, wenn ich mein Google Account verwenden kann ...)
- Features - es gibt viele Fatures, die wichtig sind. Angefangen von Sicherheitsfeatures wie zwei Faktor Anmeldung über Passwort Zurücksetzung durch den Anwender hin zu Nutzung von bestehenden Prozessen in Firmen.... und so Dinge wie Single Sign On und so sind auch nicht unwichtig....

Das aber nur ganz am Rande unabhängig von der Frage: wie wäre so etwas ggf. zu entwickeln. Wenn es nur eine Übung ist, ist es evtl. interessant, aber in der Praxis ist so eine Entwicklung eher unüblich (nach meiner Erfahrung, aber die ist natürlich etwas eingeschränkt - so war ich einen großen Teil meiner Zeit in Windows Umgebungen mit AD unterwegs ... und das für Kunden, die halt Prozesse nach ITIL hatten und somit immer auch sowas wie ein User Admin Center mit Prozessen ....


----------



## kaffeeliebhaber (3. Okt 2020)

Ich habe nun viele verschiedene Ideen bei euch gelesen, die jede für sich toll und interessant sind. Schon einmal vielen Dank dafür.

Da Programmieren für mich mein Lieblingshobby ist und ich es nicht beruflich mache, seht es mir nach, wenn ich nicht die genauen Begriffe parat habe, sie jedoch sicherlich verwirrend für euch umschreibe.  

Ihr habt mir viele interessante Aspekte geliefert. Viele Begriffe, mit denen ich nun mehr eine Suchmaschine befragen kann, die mir vorher einfach nicht bewusst waren. Und das ist eine Menge wert. Als Fachfremder ist es da einfach schwierig, auf die passenden Begriffe zu kommen.

Aber mit euren Vorschlägen komme ich sicherlich nun weiter bei meinem Projekt. Vielleicht werde ich an der ein oder anderen Stelle von meinem Fortschritt berichten. Falls es jemanden interessiert.


Also noch einmal: Dank euch alle für euren konstruktiven Vorschläge.


----------



## sascha-sphw (3. Okt 2020)

JustNobody hat gesagt.:


> - man kann existierende Identity Provider nehmen. Im öffentlichen Bereich finden sich da viele Anbieter: Facebook, Google, Microsoft, Apple, ....
> - es gibt genug (teilweise freie) Software, die da was bieten. Angefangen von dem ‚alten‘ LDAP / AD Anbietern hin zu aktuellen OAUTH Lösungen.


Ich persönlich finde Keycloak sehr angenehm, da kann ich meine Services sehr einfach absichern, mit all dem ganzen Schickimicki drum herum, ohne das ganze selber implementieren zu müssen (Was ich BTW eh nicht raten würde, wenn Du nicht schon tief in diesem Thema steckst).


----------



## Dukel (3. Okt 2020)

JustNobody hat gesagt.:


> Daher ist eine Lösung: gar kein Passwort speichern. Dies ist z.B. möglich in Windows Domänen mit Windows Integrated Authentication wie es z.B. der MS SQL Server unterstützt. Der User meldet sich dann am Rechner an mit seiner Domain Kennung an und diese Authentifizierung wird dann auch weiter genutzt.


Btw. MySql (um das es hier geht, andere DB aber auch) unterstützt Kerberos.





						MySQL :: MySQL 8.0 Reference Manual :: 6.2.17 Pluggable Authentication
					






					dev.mysql.com


----------



## kneitzel (3. Okt 2020)

Dukel hat gesagt.:


> Btw. MySql (um das es hier geht, andere DB aber auch) unterstützt Kerberos.
> 
> 
> 
> ...



Aber das bedarf dann der Enterprise Edition, oder habe ich das missverstanden?


----------



## Dukel (3. Okt 2020)

Das ist möglich.
Ansonsten soll es aber unter MariaDB frei gehen.








						Authentication Plugin - GSSAPI
					

The gssapi authentication plugin uses the GSSAPI interface to authenticate with Kerberos or NTLM.




					mariadb.com


----------

