it-swarm.com.de

Wie soll eine Anwendung ihre Anmeldeinformationen speichern?

Kontext

Bei der Entwicklung von Desktopanwendungen müssen Sie gelegentlich Anmeldeinformationen irgendwo speichern, um Ihre Anwendung authentifizieren zu können. Ein Beispiel hierfür ist ein Facebook App ID + secret , ein anderes sind MySQL-Anmeldeinformationen.

Das Speichern dieses Klartextes im Quellcode der Anwendung bietet keine echte Sicherheit, da es nicht zu mühsam ist, ein Programm zurückzuentwickeln . Das Sammeln der Anmeldeinformationen von einem Server reicht ebenfalls nicht aus, da Hacker Anforderungen problemlos selbst ausführen können. Die Verschlüsselung der gespeicherten Anmeldeinformationen macht auch keinen Unterschied, da die Anwendung Zugriff auf den Entschlüsselungsschlüssel benötigt, um die Anmeldeinformationen überhaupt verwenden zu können.


Frage

Wie kann man anwendungsspezifische Anmeldeinformationen sicher speichern? Vorzugsweise betriebssystemübergreifend.

Hinweis: Die relevante Sprache ist Java. Ich glaube jedoch, dass dies eine sprachunabhängige Frage ist.

36
Zar

Niemals Passwörter oder Kryptoschlüssel in Ihrem Programm fest codieren.

Die allgemeine Faustregel lautet: Die einzigen Anmeldeinformationen, die Sie auf dem Computer eines Benutzers speichern sollten, sind Anmeldeinformationen, die diesem Benutzer zugeordnet sind z. B. Anmeldeinformationen, mit denen sich dieser Benutzer bei seinem Konto anmelden kann.

Sie sollten keine Ihre Entwickleranmeldeinformationen auf dem Benutzer Computer speichern. Das ist nicht sicher.

Sie müssen davon ausgehen, dass alles, was auf dem Computer des Benutzers gespeichert ist, dem Benutzer bekannt ist oder vom Benutzer leicht erlernt werden kann. (Dies ist die richtige Annahme: Es ist nicht schwer, eine Anwendungsbinärdatei rückzuentwickeln, um die darin eingebetteten Schlüssel oder Geheimnisse zu lernen.)

Sobald Sie dieses allgemeine Prinzip verstanden haben, wird alles einfach. Grundsätzlich müssen Sie dann den Rest Ihres Systems und Ihr Authentifizierungsprotokoll so gestalten, dass sich die Client-Software nur mit den Anmeldeinformationen authentifizieren kann, die sicher auf dem Client gespeichert werden können.

Beispiel 1. Angenommen, Sie haben eine Facebook-App-ID und einen Facebook-App-Schlüssel, die Ihrer App zugeordnet sind (d. H. Ihrem Entwicklerkonto zugeordnet sind). Betten Sie die App-ID und den Schlüssel in die Desktop-Software ein, die Sie an Benutzer senden? Nein! Absolut nicht. Sie tun dies definitiv nicht, da dies jedem Ihrer Benutzer ermöglichen würde, Ihre App-ID und Ihren Schlüssel zu erfahren und ihre eigenen Anfragen einzureichen, was möglicherweise Ihren Ruf schädigen könnte.

Stattdessen finden Sie einen anderen Weg. Beispielsweise richten Sie möglicherweise einen eigenen Server ein, der über die App-ID und den Schlüssel verfügt und für die Anforderung an die Facebook-Plattform verantwortlich ist (vorbehaltlich entsprechender Einschränkungen und Ratenbeschränkungen). Anschließend stellt Ihr Client eine Verbindung zu Ihrem Server her. Möglicherweise authentifizieren Sie jeden Client, indem Sie jeden Benutzer sein eigenes Benutzerkonto auf Ihrem Server einrichten lassen, die Kontoanmeldeinformationen auf dem Client speichern und den Client sich anhand dieser Anmeldeinformationen authentifizieren lassen.

Sie können dies für den Benutzer völlig unsichtbar machen, indem die Client-App bei der ersten Ausführung ein neues Benutzerkonto generiert (eigene Anmeldeinformationen generiert, lokal speichert und an den Server sendet). Die Client-App kann diese gespeicherten Anmeldeinformationen verwenden, um in Zukunft eine Verbindung herzustellen (z. B. über SSL) und sich bei jeder weiteren Ausführung der App automatisch anzumelden.

Beachten Sie, dass auf dem Computer eines Benutzers nur Anmeldeinformationen gespeichert sind, mit denen Sie sich bei diesem Benutzerkonto anmelden können. Es gibt jedoch nichts, was die Anmeldung bei den Konten anderer Benutzer ermöglicht, und nichts, was Entwickler-App-Schlüssel verfügbar macht.

Beispiel 2. Angenommen, Sie schreiben eine App, die auf die Daten des Nutzers in seinem Google-Konto zugreifen muss. Fordern Sie sie zur Eingabe ihres Google-Benutzernamens und -Kennworts auf und speichern Sie sie im lokalen App-Speicher? Sie könnten: Das wäre in Ordnung, da die Anmeldeinformationen des Benutzers auf dem Computer des Benutzers gespeichert sind. Der Benutzer hat keinen Anreiz zu versuchen, seinen eigenen Computer zu hacken, da er bereits seine eigenen Anmeldeinformationen kennt.

Noch besser: Verwenden Sie OAuth, um Ihre App zu autorisieren. Auf diese Weise speichert Ihre App ein OAuth -Token) in ihrem app-lokalen Speicher, auf den Ihre App zugreifen kann Das Google-Konto des Benutzers. Außerdem muss das Google-Passwort des Benutzers (das besonders vertraulich ist) nicht im lokalen Speicher der App gespeichert werden, wodurch das Risiko von Kompromissen verringert wird.

Beispiel 3. Angenommen, Sie schreiben eine App mit einem MySQL-Datenbank-Backend, das von allen Benutzern gemeinsam genutzt wird. Nehmen Sie die MySQL-Datenbank und binden Sie sie in die App-Binärdatei ein? Nein! Jeder Ihrer Benutzer kann das Kennwort extrahieren und dann direkten Zugriff auf Ihre MySQL-Datenbank erhalten.

Stattdessen richten Sie einen Dienst ein, der die erforderlichen Funktionen bereitstellt. Die Client-App stellt eine Verbindung zum Dienst her, authentifiziert sich selbst und sendet die Anforderung an den Dienst. Der Dienst kann diese Anforderung dann in der MySQL-Datenbank ausführen. Das MySQL-Kennwort bleibt sicher auf dem Computer des Servers gespeichert und ist auf keinem Computer eines Benutzers verfügbar. Der Server kann alle gewünschten Einschränkungen oder Zugriffskontrollen festlegen.

Dazu muss sich Ihre Client-App beim Dienst authentifizieren können. Eine Möglichkeit, dies zu tun, besteht darin, dass die Client-App beim ersten Ausführen ein neues Konto für den Dienst erstellt, einen zufälligen Authentifizierungsnachweis generiert und sich jedes Mal automatisch beim Dienst anmeldet. Sie können SSL mit einem zufälligen Kennwort verwenden oder noch besser SSL mit einem eindeutigen Client-Zertifikat für jeden Client.


Die andere Regel lautet: Sie codieren keine Anmeldeinformationen fest in das Programm. Wenn Sie Anmeldeinformationen auf dem Computer des Benutzers speichern, speichern Sie diese an einem privaten Speicherort: möglicherweise in einer Konfigurationsdatei oder in einem Verzeichnis, vorzugsweise in einem Verzeichnis, das nur von dieser bestimmten App oder diesem bestimmten Benutzer gelesen werden kann (keine weltweit lesbare Datei).

30
D.W.

Es ist ein klassisches Sicherheitsproblem ohne perfekte Lösung, nur unvollkommene, und es läuft auf das allgemeinere Problem des Schutzes von Software vor Manipulationen und Reverse Engineering hinaus.

  1. Verwenden Sie eine externe Authentifizierungsmethode, die der Benutzer aktiv bereitstellen muss, um die Anmeldeinformationen zu erreichen: ein manuell eingegebenes Kennwort (dessen Hash-Digest beispielsweise zum Entschlüsseln der Anmeldeinformationen verwendet wird), einen sicheren Authentifizierungsdongle, der ein Zertifikat und einen übereinstimmenden privaten Schlüssel enthält Eingetragen in einen USB-Anschluss, einen Fingerabdruckleser, der den richtigen Fingerabdruck liefert usw. Idealerweise ist das Ergebnis keine einfache Ja/Nein-Antwort auf Ihr Programm, da dies überschrieben/gepatcht/gefälscht werden kann, sondern ein realer Wert (a kryptografischer Schlüssel), der zum Entschlüsseln Ihrer Anmeldeinformationen (oder was auch immer Sie sonst schützen möchten) erforderlich ist und direkt vom Authentifikator abgeleitet wurde. Ein Multi-Source-Ansatz, bei dem der Entschlüsselungsschlüssel im laufenden Betrieb aus verschiedenen Quellen berechnet wird (welche Quellen wirklich von Ihrem System abhängen), könnte noch besser sein.

  2. Verschleiern Sie Ihr Programm stark (automatisch und massiv), um das Reverse Engineering zu verhindern. Zwar sind statische Analysewerkzeuge auf dem neuesten Stand der Technik, aber es gibt [proprietäre, teure] Verschleierungswerkzeuge (verschleierte Compiler, Packer usw.), die das Reverse Engineering sehr zeitaufwändig, herausfordernd und mühsam machen. genug, um die Angreifer zu schicken, um nach einfacheren Zielen zu suchen. Das Hinzufügen von Schutzmechanismen gegen Debugging- und Manipulationsschutzmethoden kann die Sicherheit Ihres Programms weiter erhöhen. Richtig, Java als Bytecode-Sprache ist in dieser Hinsicht besonders anfällig, da das Dekompilieren (im Vergleich zum Dekompilieren/Disassemblieren von nativem Code) ziemlich einfach ist.

7
Harel