Das Secret System

Der Secret Generator ist ein Werkzeug das die notwendigen Schlüsselpaare erstellt, welche für eine Authentifizierung zwischen Client und Serversystemen notwendig sind.

Grundlagen

Traditionelle Benutzer/Passwort Systeme

Traditionell verwendet man für die Authentifizierung zwischen Systemen Benutzernamen und Passwörter. Dabei muss der Client (Benutzer) ein Bezeichner und ein Passwort kennen um sich gegenüber dem Server als diesen Benutzer authentifizieren zu können.

Der Bezeichner ist oft eine Schreibweise des Namens des Benutzers. Er kann aber auch auf eine andere Art mit der Person verknüpft sein, beispielsweise die Personalnummer oder eine Abkürzung.

Das Passwort ist das eigentliche Geheimnis (Secret), welches nur dieser eine Benutzer und der Server kennen darf. Dieses geteilte Geheimnis verwendet der Server um festzustellen, ob es sich bei einer Person tatsächlich um die richtige handelt. Die Person bestätigt mit dem Geheimnis, das sie echt ist.

Benutzer/Passwort System bei Server- und Client-Systemen

Soll sich ein System gegenüber einem anderen System authentifizieren, also beweisen das es wirklich dieses berechtigte System ist, machen die Wörter Benutzer und Passwort wenig Sinn. Daher ist es einfacher von einem Schlüssel (Key) und einem geteilten Geheimnis (Secret) zu sprechen.

Der Schlüssel ist dabei eine eindeutige Zahl, Zeichenfolge oder Datenblock und auch das geteilte Geheimnis ein simpler Datenblock. Menschen haben mit diesem Prozess nichts zu tun, daher macht die Terminologie „Benutzer“ hier keinen Sinn. Auch ein „Passwort“ ist etwas das gesprochen wird, und daher besser als Geheimnis oder hier als Secret bezeichnet wird.

Probleme Secret basierender Authentifikation

Speicherung der Secrets

Das Hauptproblem von Secret basierender Systeme ist die Speicherung dieses auf der Serverseite. Gelingt es einem Angreifer den Speicherort aller Secrets auszulesen, kann er sich danach ohne Probleme als ein beliebiges System ausgeben.

Um dies zu verhindern müssen die Secrets auf der Serverseite besonders geschützt werden. Das Ziel hier ist es, bei einem Verlust dieser, genügend Zeit zu gewinnen um das System wieder abzusichern.

Zu diesem Zweck werden statt der eigentlichen Secrets nur kryptografische Hashes dieser Secrets gespeichert. Dabei hat ein kryptografischer Hash zwei wichtige Eigenschaften:

  • Es ist einfach aus beliebigen Daten, wie in unserem Fall dem Secret, einen solchen Hash zu erzeugen.

  • Dagegen ist es unglaublich schwierig, plausible Daten zu erzeugen, welche genau einen bestimmten Hash generieren.

Falls nun ein Angreifer zugriff auf den Speicherort der Secrets erhält, kann er wenig damit anfangen. Zuerst müsste er plausible Daten für jeden Hash erzeugen.

Man-in-the-Middle Attacke

Ein weiteres Problem besteht darin, dass der Client irgendwann das Secret an den Server übermittelt.

Gelingt es einem Angreifer dabei die Kommunikation zwischen dem Client und Server abzugreifen und zu entschlüsseln, kann er das Secret kopieren.

Um dies zu verhindern ist es wichtig die Kommunikation zwischen dem Client und Server zu verschlüsseln. Zudem muss sichergestellt werden, dass der Client nur eine Verbindung zu einem legitimen Server aufbaut.

„Schwächen“ kryptografischer Hashes

Während für neuere kryptografische Hashes, wie SHA-256 oder SHA-512, aktuell keine bekannten Schwächen existieren, gibt es die Möglichkeit sogenannte Rainbow-Tabellen zu erstellen.

Dabei legt der Angreifer eine grosse Tabelle mit vorberechneten Hashes für alle möglichen Secrets an. Danach muss er nur noch in dieser Datenbank nach einem passenden Hash suchen und findet das dazu passende Secret.

Bei von Menschen gewählten Passwörtern ist das durchaus ein gängiges Vorgehen. Menschen tendieren dazu viel zu schwache Passwörter zu erzeugen, oft sogar mit weniger als acht Zeichen.

Besteht das Passwort beispielsweise aus maximal acht Kleinbuchstaben, so gibt es 26^8 (208’827’064’576) mögliche Passwörter. Hier lohnt sich der Aufwand eine Datenbank mit Hashes zu erzeugen.

Gesalzene Hashes (Salted Hashes)

Vor allem um von Menschen generierte Passwörter besser zu sichern, werden daher die Hashes „gesalzen“. Dabei fügt das System jedem Passwort eine bestimmte Menge zufälliger Daten hinzu. Diese zufälligen Daten werden zusammen mit dem Hash gespeichert.

Soll jetzt ein bestimmtes Passwort getestet werden, werden einfach die zu dem Benutzer gespeicherten zufälligen Daten hinzugefügt. Stimmt der Hash überein, hat der Benutzer das passende Passwort übermittelt.

Die zusätzlichen zufälligen Daten machen es schwieriger eine Datenbank mit Hashes aufzubauen. Da zu jedem Passwort ja auch Hashes für alle möglichen zufälligen Daten erstellt werden müssen.

Elimination des Menschen als Fehlerquelle

Aus den oben genannten Gründen versuchen wir den Menschen als Quelle von unsicheren Secrets zu eliminieren. Daher müssen für die Authentifizierung Schlüsselpaare mit dem Secret Generator erstellt werden.

Der Secret Generator erstellt einen zufälligen Schlüssel und Secret für den Client. Zudem erstellt er den dazu passenden gesalzenen Hash für den Server.

Das Secret besteht dabei aus 64 Zeichen, aus einem Set von 87 Zeichen. Dazu kommen zusätzliche 64 zufällige Zeichen für den Salt, aus dem gleichen Set. Das ergibt 87^128 mögliche Kombinationen und schliesst damit ein Brute-Force, also das durchprobieren von Hashes effektiv aus.

Es bleiben also nur das Auslesen des Secrets aus der Client-Konfiguration oder ein Man-in-the-Middle Angriff. In beiden Fällen müsste der Angreifer bereits Zugriff auf das lokale Netzwerk haben.

Der Secret Generator

Nachdem du das Secret Generator Werkzeugs startest erscheint das Hauptfenster. Der obere Bereich ist dabei der Eingabebereich, darunter findest du den Ausgabebereich.

../../../_images/secret-generator-main-window.jpg

Die Elemente im Secret Generator Fenster.

  • A In dem Feld Label gibst du dem Eintrag einen Namen. Dieser wird als label der Serverkonfiguration hinzugefügt.

  • B Darunter, im Feld Authorized Networks gibst du die IP-Adressen und Netzwerke ein, welche für den Eintrag zugelassen sind. Trenne dabei mehrere Einträge mit einem Leerzeichen.

    Wenn der Eintrag rot wird, ist ein Fehler in den eingegebenen Netzwerkadressen.

  • C Falls du das Schlüsselpaar für eine Authentifizierung über eine HTTPS/JSON Schnittstelle verwendest, solltest du die Option Limit key characters for HTTP authentication auswählen.

    Dabei wird ein anderer Satz von Zeichen verwendet, welcher bei dieser Art von Authentifizierung keine Probleme macht.

  • D Mit der Option Version wählst du welche Version des Schlüsselpaars generiert werden soll. Verwende hier nur Version 2, ausser du erzeugst ein Schlüsselpaar für eine sehr alte Softwareversion.

  • E Klickst du auf den Generate New Key-Pair Knopf wird ein neues Schlüsselpaar mit den aktuellen Einstellungen erzeugt. Die dazugehörigen Daten erscheinen in den Feldern unten.

  • F In diesem Bereich findest du die Werte und eine Konfigurationsschnipsel für die Client-Konfiguration. Es kann sein dass du die Namen der Werte für die Konfiguration anpassen musst, der Generator erzeugt lediglich ein Beispiel mit den am häufigsten verwendeten Werten.

  • G Darunter findest du die Werte, sowie ein Konfigurationsschnipsel für die Server-Konfiguration. Je nach Anwendung musst du möglicherweise noch weitere Werte zu dem Eintrag hinzufügen. Der Generator erzeugt hier lediglich ein Beispiel mit den Grundwerten.

  • H Mit dem Knopf Copy to Clipboard kopierst du schnell den Inhalt des Feldes auf der linken Seite in die Zwischenablage.

Das Kommandozeilen Werkzeug

Für den Fall du das Erzeugen von Schlüsselpaaren automatisieren möchtest, existiert ein Kommandozeilen Werkzeug. Dieses generiert neue Schlüsselpaare und gibt dir als Resultat XML oder JSON zurück.

Mit --help bekommst du eine Übersicht aller Optionen:

E:\>SecretGeneratorCommand.exe --help
SecretGeneratorCommand.exe [options]
Options:
--config-dir=... [list]
    Add another directory to scan for configuration files.
--config-file=... [list]
    Add another configuration file to parse.
--file=..., -o=... [string value]
    If you specify this option, the output is written to the given file instead
    of the console. An existing file is overwritten.
--format=..., -f=... [string value]
    Select the format of the secret output.
--help, -h [boolean value]
    Displays help about command line arguments.
--label=..., -l=... [string value]
    An optional descriptive label for secret entry. This label is used in the
    application for log and error messages.
--limit-for-web, -w [boolean value]
    Limit the characters in the generated secrets to a set suitable for web
    basic authentication. Use this option if you like to authenticate using a
    HTTP/JSON network interface.
--network=..., -n=... [list]
    Add an authorized network for the entry. You can specify this option
    multiple times to add multiple networks. The value has to be either an IPv4
    or IPv6 network with slash/prefix notation. Example: 10.0.0.0/24
--version=..., -v=... [integer value]
    Optional the secret version to use. Use this option if you need to create
    secrets for old software versions. By default, the latest version is used.

Optionen

--file=<file>, -o=<file>

Mit dieser Option wählst du eine Datei in welche die Ausgabe geschrieben wird. Lässt du diese Option weg, wird die Ausgabe in die Konsole geschrieben.

--format=<format>, -f=<format>

Mit dieser Option wählst du das Format der Ausgabe. Mögliche Werte sind hier:

  • xml Generiert zwei Blöcke mit XML Daten für die Konfiguration. Die beiden Blöcke werden dabei mit den Zeilen Client: und Server: getrennt.

  • json Generiert einen JSON Dokument, welches alle generierten Werte enthält.

--label=<label>, -l=<label>

Mit dieser Option kannst du den Namen des Eintrags setzen.

--limit-for-web, -w

Mit dieser Option wählst du das alternative Set von Zeichen für die Web kompatible Authentifizierung.

--network=<network>, -n=<network>

Diese Option kannst du mehrmals angeben. Dabei gibst du jedes mal eine erlaubte IP-Adresse oder Netzwerk an.

--version=<version>, -v=<version>

Mit dieser Option wählst du das Format des generierten Schlüsselpaars. Lässt du sie weg, wird automatisch die neuste Version verwendet.

Beispiele

Das folgende Beispiel ruft das Werkzeug ohne Optionen auf. Dabei wird ein Schlüsselpaar erzeugt und dieses in einem JSON Block ausgegeben:

E:\>SecretGeneratorCommand.exe
{"clientSecret": "9UOL}ItEs)xIz,;0jpN=8vt#[^u,djkT_JO;GO5kYmLN[JBT6K;sE08uot%EB5B]",
 "key": "Y+jEa;QO!$Tvpg%*[q9gf*zxWIhC)Vj.FQ:KQq=NGytofdNFw.bB|5.[6I;GcW2i","serverSecret":"M;m=U5Zr$z}~2H4,Rp)lz-+i-6DUF;ddu1J^PCw$p{DR)%IqjNeYW-)q_jQ1|z*4 WllOZewsPh7Lg9hr3Lql6Yu73SvltqEcv5B6isSEx1v2z0EGMBWZCKEYiCYaETdzOwzZgu5TTQ1B2Up9RjfHnw== V2"}

Im nächsten Beispiel wird die Ausgabe als XML gewählt und ein Netzwerk, sowie ein Name angegeben.

E:\>SecretGeneratorCommand.exe --format=xml --label=Example --network=10.0.0.0/8 --network=192.168.0.0/16
Client:
<Value name="apiKey">/m~Ez_]w5acvr{T0x#G]4L!z6}QCXK#ecE[6:{1Vxw)1^l$|Q!lz=rr15.1#hqw=</Value>
<Value name="apiSecret">~i!Gw6NE//{(X=:q#6lto:B}yO#EWTmvOK6vp2d:|0vJ)qoormfM+2PXIrv*xI~@</Value>
Server:
<ListEntry>
        <Value name="label">Example</Value>
        <Value name="authorizedNetworks">10.0.0.0/8 192.168.0.0/16</Value>
        <Value name="key">/m~Ez_]w5acvr{T0x#G]4L!z6}QCXK#ecE[6:{1Vxw)1^l$|Q!lz=rr15.1#hqw=</Value>
        <Value name="secret">_ju89a_fZ8;}ggMd4=TOwbk7*Zu8-xg17GBJmZ8Y?i1X:S=5gSy:jUUBM7z5^70s gbPHbGjFvcx9JML2zf8NX8KDSUaoEfc/4fimIrVaRrquzR1rp6dwlw1W4WWUDI0eq7LAe4m9OwJXb277C5jHQA== V2</Value>
</ListEntry>