Sicherheit

keidel22

Mitglied
Hallo
Mir geht es in diesem Thema mehr um ein allgemeines Konzept, als um eine konkrete Implementierung, da ich mit Java entwickele poste ich es hier.
Problemstellung: Für ein Netzwerk soll ein Programm entwickelt werden, welches auf mehreren PCs Clientseitig läuft. Für das Programm müssen Daten gespeichert werden(Authetifizierungen, usw.)
Da ein Benutzer den PC wechseln kann, müssen die Daten an einer zentralen Stelle (Datenbank, Datei)
gespeichert werden. Diese Daten müssen natürlich verschlüsselt werden. Das erste Konzept, welches mir in den Sinn kam, war folgendes:
Im Client-Programm wird ein Schlüssel hart kodiert, d.h. in jedem Clienten befindet sich der gleiche Schüssel. Ver und Entschlüsselung geschieht synchron beim Clienten, die Daten werden verschlüsselt übertragen und auch verschlüsselt gespeichert. Problem bei diesem Konzept: Wird beim Clienten mit einem Tool aus den class-Dateien der Sourcecode wieder hergestellt, ist sowohl der Schlüssel als auch der Algorithmus sichtbar, damit können dann die Daten dann leicht entschlüsselt werden.

Zweites Konzept: Dort wo die Daten gespeichert werden läuft ein Serverprogramm, welches synchron die Datenverschlüsselung übernimmt(das was in Konzept 1 der Client macht). Server und Client kommunizieren asynchron, d.h. der Client wählt für jede Session einen public key, sendet diesen an den Server, dieser holt die Daten aus der Datenbank, verschlüsselt sie mit dem public key des Clienten, schickt diese verschlüsselten Daten an den Clienten, dieser entschlüselt sie mit seinem privaten key. Soweit so gut, das Problem daran ist, wie erkennt der Server, dass die Anfrage von einem gültigen Clienten kommt und nicht von einem "bösen" Programm. Die erste Idee dazu war,
dem Clienten ein "Geheimnis" mitzugeben, key, id oder ähnliches. Dies führt aber wieder auf das gleiche Problem wie in Konzept1, da dieses Geheimnis aus dem Sourcecode auslesbar wäre.

Hat jemand eine Idee oder Lösung, wie man dieses Problem angehen könnte. Gäbe es z.B. eine Möglichkeit, die class-Dateien so zu verändern, dass der Sourcecode aus ihnen nicht mehr gewonnen werden kann? Wenn sehr spezifische Begriffe verwendet werden bitte mit einer kurzen Erklärung oder einem Verweis auf eine Erklärung.
Vielen Dank im Voraus für die Antworten.
 

Andi_CH

Top Contributor
Soweit so gut, das Problem daran ist, wie erkennt der Server, dass die Anfrage von einem gültigen Clienten kommt und nicht von einem "bösen" Programm. Die erste Idee dazu war, dem Clienten ein "Geheimnis" mitzugeben, key, id oder ähnliches. Dies führt aber wieder auf das gleiche Problem wie in Konzept1, da dieses Geheimnis aus dem Sourcecode auslesbar wäre.

Authentifizierung läuft IMO (ist schon einige Jährchen her) so, dass der Server dem Client auf den Request hin einen Zufallsstring sendet, dieser den mit seinem eigenen SecretKey verschlüsselt. Der Server entschlüsselt das mit dem PulibcKey des mutmasslichen Absenders. Wenn die Dechifrierung klappt ist der Absender identifiziert.

Allerdings dann haben wir Plain- und Ciphertext auf der Leitung, was auch gefährlich ist, aber in etwa so geht es (die Details weiss ich nicht mehr)

Schlüssel bzw. Geheimnisse gehören NICHT ins class-File - also musst du diese gar nicht sichern.
(Algorithmen gelten nicht als geheim - nur die Schlüssel)

Macht ja auch keine Sinn weil jeder Client ein eigenes Geheimnis braucht und du ja nicht für jeden Client neu kompilieren möchtest. Das sollte in einer speziellen Datei liegen, die mit dem PublicKey des jeweilgen Clients chiffriert ist.
 
Zuletzt bearbeitet:
T

Tomate_Salat

Gast
ich würde zweites konzept nehmen, etwa so:
Client macht sich beim Server bekannt (new Socket...). Daraufhin bekommt der Client einen publicKey zugesendet. Der Client hat eine Anmeldung und verschlüsselt diese mithilfe des PublicKeys. Der Server decodiert die Daten und gleicht die Benutzerdaten ab. Der Client sendet eine natürlich auch einen publicKey an den Server, welcher seine Daten verschlüsselt an den Clienten weiterleitet.

Anmerkung: RSA-Verschlüsselung (z.B.) ist ziemlich langsam. Deine Daten verschlüsselst du besser auf eine schnellere variante und sendest nur den (mit asnychroner-verschlüsselung) verschlüsselten key.
 
Zuletzt bearbeitet von einem Moderator:

keidel22

Mitglied
@Andi_CH

Wenn ich es richtig verstanden habe soll es so laufen: Client sender request und public key client an Server, dieser generiert einen zufälligen string, schickt diesen an den client. Der Client verschlüsselt diesen mit private key client und schickt das zurück. Der Server entschlüsselt und prüft, ob das ergebnis mit dem gesendeten string übereinstimmt.

Wenn jetzt aber ein feindliches Programm kommt, einen public und private key generiert, die anfrage an den server schickt, der server den string generiert und vom feindlichen programm den verschlüsselten string zurückbekommt und dann entschlüsselt, wird er auch auf das gleiche ergebnis kommen und annehmen, die anfrage kommt von einem ordentlichen clienten. Oder habe ich da was
falsch verstanden?

@Tomate_Salat

Gute Idee, also die eigentliche Authentifizierung erfolgt über die Anmelddaten(name,passwort) des Benutzers. Dieser gibt die Daten ein, diese werden mit dem public key des servers verschlüsselt. Der Server entschlüsselt sie und überprüft, ob das Tupel in der Datenbank vorhanden ist. Wenn ja, ist der Client authentifiziert und kann weitere Daten(verschlüsselt) vom Server erhalten. War das so in etwas deine Idee?
 

obscuri

Mitglied
Hey!
Für eine verschlüsselte Übertragung der Daten nimmst du am besten SSL/TLS.
SSL/TLS ist ein hybrides Verschlüsselungsverfahren und nutzt daher die Vorteile sowohl symmetrischer (also ein fester Key) als auch asymmetrischer Verschlüsselung (public- und private Keys). Es gilt als sicher und Java hat dafür schon fertige Implementierung mit an Bord:

JAVA + SSL Tutorial

Wenn du genau wissen willst wie das so funktioniert:
Transport Layer Security ? Wikipedia

Was die Authentifizierung angeht (also das Feststellen ob ein Client ein Benutzer ist, der mit dem Server kommunizieren darf oder nicht): Ja man kann es schon so machen, wie Andi_CH das beschreibt. Allerdings ist das wahrscheinlich doch etwas viel Aufwand für dein Szenario. Dann bräuchte auch jeder Client wieder einen geheimen Schlüssel mit dem er die Zufallsnachricht dann verschlüsselt und so weiter.

Aber die einfachere Alternative könnte doch so aussehen:
Bei dir ist es wahrscheinlich ohnehin so, dass jeder Benutzer einen Benutzernamen und ein Passwort hat. Diese Daten kannst du ja auch für Authentifizierung verwenden. Das ganze läuft dann so, als würdest du dich z.B. im Internet bei deinem Webmail-Account anmelden. In deinem Client fragst du die Benutzerdaten ab, also Benutzername und Passwort. Dann baust du mit SSL eine verschlüsselte Verbindung zum Server auf. Der Server gleich die übertragenen Benutzerdaten dann mit den Benutzerdaten aus der Datenbank ab. Wenn sie übereinstimmen kannst du wohl davon ausgehen, dass es sich um den richtigen Benutzer handelt (wenn seine Daten nicht geklaut wurden). Dann kann der Benutzer weiter über die SSL Verbindung mit dem Server kommunizieren, Daten austauschen, whatever. Wenn die Benutzerdaten nicht übereinstimmen schickst du dem Client eine Fehlermedlung und beendest die Verbindung vom Server aus.
Wenn z.B. das Passwort eines Benutzers auch verschlüsselt in der Datenbank stehen soll verwendest du dafür am besten eine Einwegverschlüsselung, also eine Hashfunktion. Auch dafür hat Java bereits alles dabei.
Was auf gar keinen Fall geht ist das Verwenden des Schlüssels im Quelltext!
Wenn du detaillierte Infos brauchst musst du doch nochmal das UseCase Szenario etwas genauer beschreiben.
 
Zuletzt bearbeitet:

obscuri

Mitglied
In einem solchen System müsste der Server die public keys seiner Clients eigentlich kennen.
Wenn also ein falscher Client ein public key/private key Paar erzeugt bringt es ihm nichts.
Der Client versucht sich anzumelden und nennt seine Identität dem Server. Der erzeugt einen Zufallsstring und sendet ihn an den Client. Der verschlüsselt dann den String mit seinem private key, den nur er kennt und überträgt die verschlüsselte Nachricht an den Server. Der entschlüsselt es mit dem public key des Clients (den er sich z.B. aus einer Datenbank holt). Wenn die Strings übereinstimmen muss es sich um den Client handeln, denn nur dieser kann den private key kennen. Wenn der Server natürlich die public keys nicht kennt würde dieses Verfahren so nicht funktionieren.
 

keidel22

Mitglied
@obscuri der Server kennt die Clienten leider nicht. Ich hatte schon daran gedacht, bei der
Installation des Clienten ( muss Installiert werden wegen Richtlinien, auch wenn es sich nur um eine
JAR-Datei handelt ) den Clienten am Server anzumelden, aber das ist schwierig, wegen dynamischer IPs.

Ich denke eine gute Lösung ist folgende:
Serverprozess läuft und wartet auf request.

1. Client sendet request an server
2. server sendet public key server (pks) an clienten zurück
3. client sendet pks(name,passwort) an server
4. server bildet private key server(pks(name,passwort)) und prüft, ob das resultierende
Tupel in der Datenbank vorhanden ist.
5. falls ja bekommt der Client das OK und kann weitere Daten anfordern(in der Datenbank stehen
pro Benutzer noch weitere Daten, z.B. Rechte). Der Serverprozess sorgt dafür, dass ein Client nur die Daten auslesen kann, die zu seinem (name,passwort)-Tupel gehören.
6. falls nein bekommt client eine meldung zugang verweigert oder sowas, die dann an den
Benutzer weitergegeben wird.

Sieht jemand in diesem Konzept eklatante Sicherheitslücken?
Heute wird das Konzept der Infrastruktur vorgestellt, die sind für den Bereich Sicherheit
zuständig, mal sehen was sie dazu sagen.
 

FArt

Top Contributor
Ich verstehe nicht, warum du das alles selber machen möchtest... ich würde Client-Server Infrastruktur wählen (z.B. Spring oder einen Webserver oder gar einen Applicationserver) und mit Spring-Security bei Spring oder sonst mit JAAS und einem Serverzertifikat arbeiten. Fertig... keine manuelle Verschlüsselung, kein Schlüsselgeschiebe usw.
Das ist einfach die Sache mit dem Rad, welches nun mal leider schon erfunden ist... und wie es aussieht hast du nicht viel Erfahrung in der Stellmacherei...
 

keidel22

Mitglied
@Fart du hast Recht, mit diesem Thema habe ich noch nicht viel Erfahrung.

Ich hatte auch schon an ein Framework gedacht, zwei Gründe sprechen da so ein bisschen dagegen:

1. Die Speicherung der Daten wird nicht so ein großes Theme werden, es muss nicht so viel gespeichert werden und die Struktur ist nicht so komplex. Ist halt die Frage, ob es sich lohnt,
sich deswegen in so ein Framework einzuarbeiten. Natürlich kann man dagegen argumentieren, dass dieses Szenario sowieso in abgewandelter Form immer wieder vorkommt und man sich daher sowieso irgendwann mit einem entsprechenden Framework befassen muss.

2. In entwickele das Programm für ein Firmennetzwerk und dort wird sich immer relativ schwer getan mit der Einführung neuer Programme (die Clienten haben z.B. nur java 1.4 ). Wenn ich einen Applicationserver wie z.B. JBoss nutzen möchte, müsste ich begründen, wieso der installiert werden muss, dann muss jemand dafür die Verantwortung übernehmen, die Installation des Servers muss qualifiziert werden usw. Es ist leider oft so, dass in Unternehmen die Architekturen relativ veraltet sind.

Kleine Frage, mit JBoss habe ich schon gearbeitet, aber da ging es nicht um ein Szenario mit Verschlüsselungen. Welches Framework wäre denn für das Szenario hier am besten geeignet und wie hoch ist da ungefähr der Einarbeitungsaufwand.
 

Andi_CH

Top Contributor
@Andi_CH

Wenn ich es richtig verstanden habe soll es so laufen: Client sender request und public key client an Server, dieser generiert einen zufälligen string, schickt diesen an den client. Der Client verschlüsselt diesen mit private key client und schickt das zurück. Der Server entschlüsselt und prüft, ob das ergebnis mit dem gesendeten string übereinstimmt.

Wenn jetzt aber ein feindliches Programm kommt, einen public und private key generiert, die anfrage an den server schickt, der server den string generiert und vom feindlichen programm den verschlüsselten string zurückbekommt und dann entschlüsselt, wird er auch auf das gleiche ergebnis kommen und annehmen, die anfrage kommt von einem ordentlichen clienten. Oder habe ich da was
falsch verstanden?
Es kann schon sein dass da was nicht stimmt, aber frag doch das besser in einem Matheforum nach.
Ich hab mich 1994 das letzte mal mit Kryptographie auseinandergesetzt.

Aber etwas weiss ich - public keys sind public - das heisst sie können genau so gut über das Netz geschickt werden.

Ich erinnere mich aber jetzt daran, dass IMO eine sichere Auhentifizierung ohne gemeinsames Geheimnis nicht möglich ist.
Siehe auch hier im ersten Abschnitt.
 
Zuletzt bearbeitet:

FArt

Top Contributor
@Fart du hast Recht, mit diesem Thema habe ich noch nicht viel Erfahrung.

Ich hatte auch schon an ein Framework gedacht, zwei Gründe sprechen da so ein bisschen dagegen:

1. Die Speicherung der Daten wird nicht so ein großes Theme werden, es muss nicht so viel gespeichert werden und die Struktur ist nicht so komplex. Ist halt die Frage, ob es sich lohnt,
sich deswegen in so ein Framework einzuarbeiten. Natürlich kann man dagegen argumentieren, dass dieses Szenario sowieso in abgewandelter Form immer wieder vorkommt und man sich daher sowieso irgendwann mit einem entsprechenden Framework befassen muss.

2. In entwickele das Programm für ein Firmennetzwerk und dort wird sich immer relativ schwer getan mit der Einführung neuer Programme (die Clienten haben z.B. nur java 1.4 ). Wenn ich einen Applicationserver wie z.B. JBoss nutzen möchte, müsste ich begründen, wieso der installiert werden muss, dann muss jemand dafür die Verantwortung übernehmen, die Installation des Servers muss qualifiziert werden usw. Es ist leider oft so, dass in Unternehmen die Architekturen relativ veraltet sind.

Kleine Frage, mit JBoss habe ich schon gearbeitet, aber da ging es nicht um ein Szenario mit Verschlüsselungen. Welches Framework wäre denn für das Szenario hier am besten geeignet und wie hoch ist da ungefähr der Einarbeitungsaufwand.

Es muss kein großer Applikationserver oder so sein... der Vorteil ist hier eben, dass hier schon alles fertig wäre.
Logik in ein EJB packen (oder Webservice) und alles was mit Authorisierung oder Authenitifzierung zu tun hat muss nur noch konfiguriert werden... kein Code. Bei Java-Clients minimaler Code...

JAAS: JAAS Reference Guide

Bzgl. Verschlüsselung: explizite Verschlüsselung fällt weg, kümmer dich nicht darum.

Ich finde es jedes mal seltsam, dass die Firmen sich schwer tun eine sinnvolle Laufzeitumgebung für ihre Software zu installieren, aber ein selbst gefrickeltes Sicherheitskonzept akzeptieren. Es ist leichter und sicherer einen abgespeckten JBoss mit JAAS zu administrieren als ein ordentliches Sicherheitskonzept selber umzusetzen... oder, wenn es leichtgewichtiger sein soll, eben Spring und Spring-Security... aber mein Tipp: mach es nicht selber.

[EDIT]
Chapter8.Security on JBoss
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben