C# Richtiges Übermitteln von Passwörtern

Kokujou

Lieutenant
Registriert
Dez. 2017
Beiträge
929
Hallo :)
Ich stehe davor mal eine halbwegs ernsthafte App zu schreiben und da komme ich unweigerlich zu der Frage:
Wie übermittle ich Passwörter?
Ich habe einen Server, der widerum mit einem MySQL-Server kommuniziert.
1. Frage: Warum zur Hölle sollte man sowas machen? einen Apache-Tomcat Server der mit einem MySQL-Server kommuniziert? Warum schreibt man die Anfrage nicht gleich auf den MySQL-Server? Was sollen die Umwege? aber gut.

Der Hauptpunkt: Wie soll ich die Psaswörter übertragen? Ich will ja einen gewissen Sicherheitsstandard gewährleisten auch wenn es noch nicht SO ernst ist. Soll ich MD5-Passwörter verwenden und auch nur in MySQL MD5 verwenden und das dann so abgleichen? Oder gibt es noch eine bessere Variante?
Ich kenne mich da gar nicht aus.
 
1) Man stellt eine Datenbank nicht direkt ins WAN. Selbst wenn man das täte, müsstest du in Folge ja DB credentials in die App legen -> damit ist alles offen.

2) TLS im Tomcat einrichten. Dann kannst du auch ohne Sorgen das Passwort im Klartext über die Leitung schicken und dann im Server hashen+salten, bevor es ab in die DB geht.
 
MD5 ist so 90er. Du kannst heutzutage jeden MD5 Hash in kürzester Zeit knacken. Für Datei Checksummen sicherlich okay, aber NICHT für Passwörter. Greif zu BCrypt oder ähnlichem.
 
Okay und jetzt tun wir mal so als hätte ich nichts von dem was ihr gerade gesagt habt verstanden.
Also mit hashen komme ich noch mit aber warum salze ich jetzt mein Passwort? Was ist TLS und wie richte ich das im Tomcat ein? es hat mich schon ein haufen arbeit gekostet diesen Server überhaupt einzurichten und da irgendwie eine Java Anwendung zum starten zu kriegen.
Ich arbeite übrigens mit Xamarin für die App, was es auch nicht viel leichter macht.

Und zur 1. Frage: Warum? Auch in der MySQL datenbank kann man Funktionen schreiben und ob nun Server A zu Server B sendet und da die Daten herkriegt oder ob man gleich zu Server B sendet... ich verstehs nicht... Und was heißt Credentials in die App packen das muss man doch sowieso wie soll man sich denn sonst anmelden? Irgendwie muss ja auch der Server auf die Daten zugreifen können und am Ende liegen Benutzerdaten immer in der app denn da muss der Benutzer sie ja eingeben um sich einzuloggen.
 
Also ein bisschen solltest Du Dich schon selbst einlesen, auch wenn alles neu für Dich ist.
TLS ist ein Verschlüsselungsverfahren.
Salten heißt vorm hashen noch einen Randomstring anzuhängen und den mitzuspeichern, damit ein gleiches Passwort nicht den gleichen Hash ergibt. Somit kennst Du wenn Du einen Hash geknackt hast nicht automatisch alle anderen Accounts mit dem gleichen Passwort...
 
Alle Sprachen mit einer maschinenunabhängigen Zwischensprache (.NET, Python, Java) haben ein großes Problem: Die lassen sich sehr einfach decompilieren und erreichen vom Quellcode her fast den Originalzustand (für .NET speziell .NET Reflector oder ILSpy). Also ist jeglicher selbstausgedachter Algorithmus oder gar Credentials für den DB Server praktisch offen einsehbar. Deshalb die Tomcat Applikation welche eine Schnittstelle bietet.
 
Du salzt das Passwort, damit 2 Leute, die zufällig das gleiche Passwort benutzen, nicht den gleichen Hash haben. Knacke ich per rainbow table das Passwort des einen, hab ich direkt ein Dutzend andere mit erwischt.

TLS ist Transport Layer Security. Details kannst du dir ergoogeln. Kurz - Verschlüsselung auf Transportebene, d.h. zuerst wird ein sicherer Kanal erstellt, in dem dann sicher gefunkt werden kann. Dafür brauchst du ein Zertifikat. Das darf selbst-signiert (also selbst erstellt) sein, kannst du aber auch kaufen (für eine bestimmte Domain, die auf deinen Tomcat zeigt) oder du nutzt Let's Encrypt (kann ich empfehlen).

Die DB credentials darf nur dein Tomcat wissen. Die liegen also auf deinem Server und sonst nirgendwo. Wenn ich in deiner App DB credentials finde und eine JDBC-URL dazu, dann bearbeite ich die Daten in der DB wie ich will oder lösche einfach alles.
Der Tomcat (oder eben irgendein anderer Anwendungsserver) dient hier als Indirektion, in der man nach Belieben verschiedene Arten der Authentifizierung und Autorisierung implementieren kann. Der User meldet sich dort mit seinen individuellen Daten an und der Server weiß dann, was eben dieser User darf und was nicht. Löst der User nun durch seine Aktion in der App einen Zugriff auf die DB aus, weil ein Datensatz angelegt/gelöscht/geändert werden soll, dann kannst du beliebige Logik zwischenschalten, um das kontrolliert geschehen zu lassen oder eben abzulehnen.

Mir fallen noch ein paar andere Gründe ein, aber das sollte schon reichen, um dich zu überzeugen.

Und es tut mir leid, dass dich das ganze Thema überfordert, aber IT und insbesondere die Sicherheit da, ist kein Spielzeug. Umso weniger, wenn du mit den Daten Dritter hantierst. Bloß weil du selbst Fliesen verlegen kannst, bildest du dir ja hoffentlich auch nicht ein, du könntest ein Haus bauen. Architekt, Statiker, Elektriker usw. haben ihre Daseinsberechtigung und viele Jahre studiert und praktisch gearbeitet, um das nötige Wissen anzuhäufen. Das ist in der IT nicht anders.
 
Zuletzt bearbeitet:
Keine Sorge ich bin nicht größenwahnsinnig es ist auch keine Kommerzielle App oder überhaupt etwas das benutzt wird sondern lediglich im Rahmen meines Studiums und da möchte ich eben bestmögliche Ergebnisse erzielen :)

Wie baue ich denn jetzt TLS in Tomcat ein ist das wieder so ein Akt der mich eine Woche Arbeit kostet oder ist das nur 1-2 Klicks und ne Zeile Text?

Und mit dem Salzen... Ich hänge an das PW einen Random String an. Und den String schreibe ich mit in die Datenbank oder hab ich das jetzt falsch verstanden? OK soweit sogut.

Und wegen der Anwendung: OK dass der Quellcode so einfach einlesbar ist wusste ich nicht das ist gut zu wissen und so eine Technik hätte ich öfters mal gebrauchen können. Also Schicke ich praktisch irgendwelche nicht-DB credentials an den Server und löse die sozusagen in DB_credentials auf. Also sagen wir mal man hat einen Account User auf der DB und 200 Accounts die alle die Berechtigung deieses Accounts haben. Und wenn man dann einen User Account eingibt sendet der Tomcat Server die aufgelösten DB-credentials an die DB hab ich das jetzt richtig verstanden?
Macht zumindest mehr Sinn bis jetzt hab ich die einfahc im Klartext mitgesendet natürlich nur lokal zu testzwecken XD

Jetzt interessiert mich nur noch der KOmmentar von benneque wegen dem MD5 ist so 90er Jahre gibts da was anderes was sich halbwegs unkompliziert regeln lässt?

Ach und bevor ichs vergesse: TLS ist, wenn cih das jetzt richtig verstanden habe für die Kommunikation zwishcen Server und Datenbank. Dann brauche ich aber was für die Kommunikation zwischen App und Server, dass halbwegs sicher ist. MD5 reicht da ja sicher nicht aus.
 
Zuletzt bearbeitet:
Passwörter: bcrypt
​Anwendung: Stell es dir vor wie eine Webseite (CB z.B.), da meldet man sich an, bekommt ein Cookie, mit dem hat man dann Rechte (oder auch nicht).
​CB läuft z.B. auf PHP mit nginx, Tomcat ist dein Equivalent dazu. Du rufst jetzt ne Seite auf (z.B. dein Kontrollcenter), PHP bekommt dein Cookie vom Browser (du bist ja schon angemeldet), schaut in der Datenbank nach (das ist bei CB MariaDB, bei dir MySQL), und stellt fest, dass dein Cookie zu dir gehört und zeigt dir deshalb dein Kontrollzentrum an (Daten kommen aus der Datenbank, das Darstellen übernimmt PHP).

​Deine DB hat i.d.R. nur einen Nutzer, der ist im Tomcat hart kodiert (aber den kontrollierst ja du, also kann keiner außer deine Webseite auf die DB zugreifen), die Nutzer der Seite sind virtualisiert (z.B. über ne Tabelle user(id,nick,name,pw,email)), wer was darf ist Anwendungslogik.

EDIT: Tomcat TLS: https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html
​EDIT2: TLS ist eine Transportverschlüsselung, stell es dir vor wie eine sichere Telefonleitung, wenn du mit einem Spitzel telefonierst, hast du verloren, aber abhören kann dich keiner.
​EDIT3: Wie bei TLS könntest du eine richtig coole PW-Strategie fahren: Zertifikate, jeder Nutzer hat eins, du legst den öffentlichen Teil ab und der Nutzer signiert sein Request mit seinem Zertifikat. Das wäre allerdings deutlich komplizierter als jeder Passwortansatz, aber deutlich sicherer.
 
Zuletzt bearbeitet:
Kokujou schrieb:
Jetzt interessiert mich nur noch der KOmmentar von benneque wegen dem MD5 ist so 90er Jahre gibts da was anderes was sich halbwegs unkompliziert regeln lässt?

MD5 war halt u.a. nie für Passwörter ausgelegt und ist ohne Salt mittels Rainbow Tables in nullkommanichts wertlos für Passwörter. Daher die Empfehlung bcrypt. Das übernimmt auch gleich das Salting und Hashing mit mehreren Rounds für dich. Heißt: Funktioniert out of the box mit allen wichtigen Sicherheitsmerkmalen.

In welche Sprache bzw. mit welchem Framework willst du eigentlich arbeiten? Wenn es Java sein soll, würde ich dir Spring Boot an's Herz legen. Da kriegst du alles aus einer Hand. Security, Datenbankverbindung, REST, etc. pp. (und noch 100000 andere Sachen) und so ist auch schon mit drin. Und (meiner Meinung nach das Wichtigste überhaupt für Einsteiger): Es gibt zu allem haufenweise Tutorials im Netz.
 
Also die Serveranwendung mit Tomcat ist natürlich in Java, die Anwendung mache ich mit Xamarin, C#. Xamarin selbst ist katastrophal die Doku und Hilfe dazu bpraktisch nicht vorhanden und die möglichkeiten da aktiv zu werden sind gleich 0. Das sage ich inzwishcen jedem ders hören will XD

Also ich nehme an bcrypt ist ein Verschlüsselungstool wie benutze ich das denn? Gibts das bei NuGet als Erweiterung oder wie sieht das aus? Ich nehme an damit verschlüsselst du auf Anwendungsseite dein Passwort und schickst es dann an den Server. Muss man das TLS-Zeug auch in der anwendung und der Datenbank einstellen oder reicht es aus wenn man das auf dem Server macht?

Der Teil mit der Anwendung wird mir allerdings weniger klar... Du meldest dich an der Anwendung an aber dann müsste die Anwendung ja, wenn es heir noch garkeine Kommunikation an diesem Punkt gibt, dann müssten die Infos ja hardgecodet sein?! das ist doch nonsens. Selbst verschlüsselt ist das doch viel zu heikel.
Ich hätte bis jetz gedacht es läuft so:
Anwendung -> Eingabe der Benutzerdaten -> Verschlüsseln mittels bcrypt -> Senden an den Server über TLS -> Prüfen der Berechtigungen und anwenden der Datenbankbefehle -> ...

Ein kleines Addendum: Ich hab MD5 eigentlich nie verstanden. Wenn man Texte oder sogar Quellcode damit verschlüsselt riskiert man doch mehrdeutigkeiten. Also 2 Zeichenketten doer sogar mehr mit dem gleichen MD5 Hash. Und das soll jetzt alles in der Rainbow Tabelle stehen? Da hat sich ja einer Mühe gemacht. Vor allem weil MD5 ja nur Hexadezimal ist und damit sogar noch zweideutiger ist
 
Zuletzt bearbeitet:
halt-stop.jpg

Dein Client kommuniziert mit dem Server über TLS - also über einen verschlüsselten Kommunikationskanal.

Der Client überträgt das Passwort im Klartext an den Server. Durch TLS sieht von außen keiner was vom Passwort.

Der Server benutzt dann bcrypt und verschlüsselt das Passwort und speichert das verschlüsselte Passwort in der Datenbank.

Wenn der Client sich wieder einloggt, dann muss der Server überprüfen, ob das Passwort gültig ist. Der Server darf niemals(!) dem Client blind vertrauen. Und muss selbst alles überprüfen. (Das gilt auch für den Hashing Algorithmus, das Salt, etc. pp.)

bcrypt ziehst du dir einfach via Maven oder Gradle in dein Projekt.
 
Zuletzt bearbeitet:
Okay ich hab jetzt denke ch alles verstanden, danke für die viele Hilfe! Ich mag das Forum hier :)

Aber nch eine etzte Frage um etwas zurück zu gehen:
Warum ein Extra-Server? Ein MySQL-Server kann doch das gleiche. Sie haben sogar eine Accountverwaltung. Man loggt sich erstmal mit einem readonly Gastaccount ein, da kann also erstmal gar kein Schaden entstehen. Dann sendest du da auch via TLS deine Daten, lässt sie von dem DB-Server überprüfen. Und in der anwendung kann man ja auch verschlüsseln. Ich versteh noch nciht wo das Extra Risiko ist. Ist es nicht sogar noch ein größeres Risiko wenn man noch einen Kommunikationsweg hat?
 
Tja, wenn das so einfach wäre :D

Natürlich kannst (nicht 'sollst'!) du den Server dazwischen weglassen. Technisch funktioniert das problemlos. Keine Frage.

Allerdings ist das Benutzer Management, die Rechte Verwaltung und das (nicht vorhandene) Session Management auf SQL Servern ziemlich bescheiden.

Einfaches Beispiel:
Du hast eine App für ein Adressbuch. Jeder Nutzer kann da Kontakte eintragen. Jetzt musst du aber irgendwie jeder Zeile in der Datenbank sagen: "Du gehörst Nutzer X und nur der darf dich ändern oder löschen".

Du hast also 2 (unbrauchbare) Optionen:
1. Diese Einschränkung entfernen, sodass jeder alles löschen und bearbeiten darf. Löst das Problem nicht.
2. Diese Einschränkung mit in die SQL Abfrage packen. Und schon hast du ein Problem: Die SQL Abfragen werden auf dem Client erstellt. Also kann auch jeder Nutzer die Abfrage editieren wie er will. D.h. ein technisch versierter Nutzer (also quasi Hacker) baut einfach das Query um, liest fremde Daten aus, etc. pp.
Dein Client erstellt zwar das SQL Query, aber niemand hindert den Nutzer daran, einen eigenen Client zu schreiben und dann in der Datenbank zu machen wozu er Lust hat. Dafür braucht's einen zwischengeschalteten Server.

Und du hast auch keinen extra Kommunikationsweg, weil die Datenbank so eingerichtet wird, dass sie ausschließlich von deinem Server Programm erreichbar ist. Es gibt GENAU EINEN Kommunikationsweg: Client App -> Server App -> Datenbank.

EDIT: Komplexeres Beispiel:
In modernen Applikationen arbeitet man immer häufiger mit mehreren Datenbanken parallel. Da wird dann z.B. MySQL für alle normalen Daten genutzt, aber dazu kommt dann noch Elasticsearch für Text Suchen (z.B. finde alle Bücher, deren Inhalt das Wort "Lucene" enthält - ähnlich wie Google) und dann noch Neo4j für Graphen (z.B. welche Freunde meiner Freunde über 3 Ecken stehen noch nicht in meiner Freundesliste?)
Und die Koordination dieser Datenbanken will man nicht dem Client überlassen. Vor allem wenn man 10 Datenbankabfragen für eine Antwort an den Client machen muss. Dann braucht der Client 10x50ms, aber der Server halt nur 10x1ms, weil die Datenbanken im gleichen Netzwerk liegen).
 
Zuletzt bearbeitet:
Weil das hier immer wieder verwechselt wird: MD5 und BCrypt sind/nutzen Hashverfahren und sind keine Verschlüsselung! Letztere kann man rückgängig machen, die anderen nicht.

Und ein Praxisbeispiel für TLS: Wenn in der Adressleiste deines Browsers ein grünes Schloss zu sehen ist, ist die https-Verbindung höchstwahrscheinlich mit einem TLS-Protokoll verschlüsselt.
 
Kokujou schrieb:
Ein kleines Addendum: Ich hab MD5 eigentlich nie verstanden. Wenn man Texte oder sogar Quellcode damit verschlüsselt riskiert man doch mehrdeutigkeiten. Also 2 Zeichenketten doer sogar mehr mit dem gleichen MD5 Hash. Und das soll jetzt alles in der Rainbow Tabelle stehen? Da hat sich ja einer Mühe gemacht. Vor allem weil MD5 ja nur Hexadezimal ist und damit sogar noch zweideutiger ist

Das merkt man. MD5 ist keine Verschlüsselung! Es ist ein Hash und ein Hash kann niemals kollisionsfrei sein, das ist richtig, da eine unendliche Zeichenmenge auf eine fest definierte Menge an Zeichen abgebildet wird. Der Algorithmus ist natürlich so designt, das Kollisionen weitestgehend vermieden werden. Der Sinn ist in der Regel festzustellen ob etwas verschieden ist, ist der Hash verschieden ist der Inhalt auch verschieden. Und ja es gibt Leute, die sich die Mühe machen, solche Hashes zu sammeln, wie naiv bist Du denn? Wenn man mehrere Passwortdatenbanken klaut und etwas programieren kann, geht das relativ schnell, das tippt ja niemand von Hand ab... :rolleyes:

Kannst ja mal Deine Passwörter hier ausprobieren: https://haveibeenpwned.com/Passwords
 
Naja trotzdem sind das... 16^(32?) Kombinationen das dürfte eine Weile dauern. aber ok ^^ übrigens mein sicherstes Passwort wurde nicht ge... pwned :p Und ja ich steh mit den Fachbegriffen etwas auf Kriegsfuß wie MD5 Funktioniert weiß ich ja wie man sieht ^^ das heißt ich kenne nicht den Algorithmus im Detail aber... nunja.

Aber wieder zum Thema: was ich gemacht hätte in dem einfachen Beispiel: Man erstellt einen readonly-user zur Auslese des Passworts kann doch dann bestimmt eine Funktion in der Datenbank aufrufen, mit der man sich mit einem anderen Benutzer identifizieren kann und so die Anfrage abrufen, oder? Ich meine kann man den direkten Zugriff der Datenbank nicht untersagen und den nur über die MySQL-Funktionen gewährleisten? Du könntest natürlich auch Spaßeshalber jede Zeile mit einer anderen Verschlüsselung versehen die auf dem Passwort basiert. Da gibts bestimmt einige Lösungen.

Die App die ich entwickle hat z.B. einen Bereich der komplett readonly ist, weil da niemand reinzuschreiben hat, und danach nur noch die Nutzertabelle, wo ich vielleicht noch ein paar Statistiken abspeichere. Meine Lehrerin will natürlich dass ich das Prinzip erlerne aber nunja ^^
 
Du kannst theoretisch für jeden Nutzer ein Datenbanknutzer einrichten, aber abgesichert bekommst du das nie. Warum:

​Ein Nutzer kann auf eine Tabelle (oder View) Lese oder Schreibrechte bekommen. Jetzt steht aber z.B. in der Tabelle private_messages(from_id,to_id,text) ja jede Nachricht drin. Also können die Nutzer entweder alle oder gar keine privaten Nachrichten lesen.

​Also braucht jeder Nutzer ne eigene Datenbank, das ist aber nicht die Idee einer Datenbank.

​Die Flexibilität einer Datenbank ist nicht genug für normale Anwendungen, daher hat quasi jede Webseite nur einen Datenbanknutzer, der alles darf.

​Das Problem mit MD5: Kenn ich den Hash, kann ich ein Passwort generieren, was diesen Hash hat (Hashkollision). Das das nicht deins ist, ist nicht relevant, weil das Programm dann denkt, dass es das richtige PW ist. Das ist bei bcrypt viel schwieriger (mglw. unmöglich mit der HW der nächsten 10 Jahre).
 
@Hancock: Selbst wenn jeder eine eigene Datenbank hätte ... überleg mal :D
Beispiel: Nutzer1 sendet Nachricht an Nutzer2. Jeder Nutzer hat seine eigene Tabelle für Nachrichten. Wie bekommst du nun die Daten von Nutzer1 in die Datenbank von Nutzer2 geschrieben? Genau: Gar nicht. (oder jeder hat überall Lese- und Schreibrechte, aber dann sind es auch keine "privaten" Nachrichten mehr)
 
Oder du legst für jede Nutzerkommunikation ne eigene Datenbank an :p
Aber ok ich glaub ich habs verstanden ^^

Jetzt nochmal zum TLS: Ich habs jetzt installiert, braucht man unbedingt ein zertifikat? Ich krieg grad so eine "Ausnahmeregel bestätigen" Seite. Wenn ich jetzt mit meiner App ne Post-Anfrage schicke kommt es dann da auch zu Problemen?
Ich hab ja schließlich nur localhost und werde das alles höchstens über ne dynamische IP Freigeben, wenn ich das denn hinkriege (schlechte Erfahrungen^^). Darum wirds glaub ich etwas schwer ein Zertifikat zu kriegen.
 
Zurück
Oben