Muss ich einen privaten Schlüssel in einer Datei speichern?


7

Ich habe eine db-gesteuerte Anwendung, die über ssh mit einem anderen Server kommunizieren muss. Die Web-App kann ein Schlüsselpaar generieren und dem Benutzer den Pubkey geben, oder sie kann den unverschlüsselten privaten Schlüssel in einem Feld in einem Webformular akzeptieren. Anschließend verschlüsselt es den Schlüssel mit reversibler Verschlüsselung und speichert ihn in seiner Datenbank.

Wenn die Web-App mit dem SSH-Server kommuniziert, muss ich den privaten Schlüssel entschlüsseln und ihn auf die eine oder andere Weise für SSH bereitstellen. Ich könnte eine sichere temporäre Datei mit erstellen mktemp, ssh darauf zeigen und dann die Datei zerstören, aber das ist zusätzliche Arbeit, die den Schlüssel auf eine neue Weise verfügbar macht, die anscheinend nicht notwendig sein sollte. Ich habe mir angesehen man ssh, man ssh-agentund man ssh-add, aber es scheint keine Möglichkeit zu geben, den Schlüssel zu verwenden, ohne ihn zuerst einer Datei hinzuzufügen. Was vermisse ich?


Wenn Sie die Standardwerkzeuge verwenden möchten, müssen Sie den Schlüssel über eine Datei bereitstellen. Natürlich können Sie auch Ihren eigenen SSH-Client / SSH-Agenten implementieren und den Schlüssel direkt aus der Datenbank entschlüsseln
Ulrich Dangel

@UlrichDangel Würden Sie mich so freundlich auf die Dokumentation zur Implementierung eines SSH-Agenten verweisen?
Kojiro

Nein, da ich keine habe, aber es sollte eine Beschreibung des SSH-Agentenprotokolls svnweb.freebsd.org/base/vendor-crypto/openssh/dist/…
Ulrich Dangel

Besser als alles neu zu implementieren, sollte ein einfacher Patch für eine vorhandene Implementierung den Trick tun.
Peterph

@peterph Das ist eine gute Idee, aber ich möchte immer noch eine Spezifikation haben, mit der ich arbeiten kann.
Kojiro

Antworten:


4

Wenn Sie die vorhandenen Tools wie ssh/ verwenden möchten, ssh-agentmüssen Sie den Schlüssel als Datei bereitstellen.

Eine andere, vielleicht praktikablere Lösung besteht darin, entweder a direkt zu implementieren ssh Client in Ihrer Anwendung zu und von Bibliotheken von Drittanbietern wie JSch abhängig zu sein oder entweder ssh/ ssh-agentzu erweitern, um den Schlüssel direkt aus Ihrer Datenbank zu empfangen und zu entschlüsseln.


4

Dateien sind die Hauptmethode für den Datenaustausch zwischen Anwendungen. Es muss keine Festplattendatei sein. Dies kann eine Datei im temporären Speicher oder eine Pipe sein. Sie können eine Schlüsseldatei fütternssh-add über ihre Standardeingabe , solange die Schlüsseldatei nicht kennwortgeschützt ist¹ (und da die Schlüsseldatei verschlüsselt gespeichert wurde, gibt es keinen Grund, ob sie darüber hinaus kennwortgeschützt ist).

Alternativ können Sie nichts Besonderes tun und die Datei in ein speichergestütztes Dateisystem wie /run( /dev/shmoder /tmpoder was auch immer Ihre Distribution bietet) schreiben .

Alternativ können Sie die private Schlüsseldatei ohne externe Verschlüsselung aufbewahren, sondern ein Kennwort eingeben. Verwenden Sie ein langes, zufällig generiertes Kennwort und speichern Sie dieses Kennwort in der Datenbank.

¹ Drosseln Sie experimentell ssh-addkennwortgeschützte Schlüsseldateien, die nicht durchsucht werden können, z. B. Named Pipes.


3

Entschuldigung, keine Antwort, aber zu lang für einen Kommentar, der meiner Meinung nach vorhanden ist.

Wichtig ist, was Sie erreichen möchten, indem Sie den Schlüssel verschlüsselt in der Datenbank speichern.

Ein Angreifer, der auf die temporäre private Schlüsseldatei zugreifen kann, kann auch den Speicher des SSH-Client-Prozesses lesen (und somit trotzdem auf die Schlüsseldaten zugreifen), da beide Daten grundsätzlich die gleichen Zugriffsberechtigungen haben müssen - versuchen Das Ausblenden der Datei scheint sie nicht sicherer zu machen.

Wenn Sie unterschiedliche Benutzer für die Datenbank-, Webapp- und SSH-Verbindung verwenden, indem Sie den Schlüssel in der Datenbank speichern, in der Webapp entschlüsseln und an SSH weiterleiten, öffnen Sie nur potenzielle Angriffsmethoden, indem Sie den Schlüssel über den gesamten Prozess verteilen. Wenn Sie nur einen Benutzer für all diese verwenden (db, app, ssh), gewinnen Sie nichts außer der Komplexität des Codes.

Der einzige Vorteil scheint eine einfachere Übertragung des Systems auf einen anderen Host und ein potenzieller Gewinn für den Fall zu sein, dass die Datenbankdaten gestohlen werden, die Webanwendung (die AFAIU enthält den Entschlüsselungsalgorithmus und das Kennwort) jedoch nicht. Aber ist das wahrscheinlich?

Wenn Sie den Schlüssel schützen möchten, können Sie auch die interne Verschlüsselung der Schlüssel durch ssh verwenden und diese beim Starten Ihres Dienstes in einen ssh-Agenten laden (denken Sie daran, ihn zu entfernen, wenn er beendet wird!). Aber denken Sie auch hier daran, dass der ssh-Agent die Schlüssel im Speicher unverschlüsselt hält, damit sie möglicherweise gelesen werden können. Nochmals: Ist dies das Problem, das Sie lösen möchten?

Wenn Sie nur die Kommunikation zwischen zwei Computern schützen müssen, ist dies stunnelmöglicherweise besser als ssh.

Und schließlich zur Frage: Für OpenSSH ( portabel ) sollte das Schreiben eines einfachen Patches, mit sshdem der Schlüssel wie sshdbei der AuthorizedKeysCommandOption aus einem anderen Prozess gelesen werden kann, relativ einfach sein.


Ich weiß zu schätzen, was Sie sagen, und Sie haben Recht, meine Annahmen in Frage zu stellen und zu fragen, welches Problem ich löse . jedoch ist Ihre Antwort zu spezifisch für die Umwelt um meine Frage (die Webapp und db) und (wie Sie sagen) , dass es nicht die Frage beantworten , selbst.
Kojiro

Klar, ich wollte das nur zum späteren Nachschlagen schreiben. Ziemlich oft habe ich gesehen, dass Leute (falsch) ssh in Situationen verwenden, in denen etwas anderes eine bessere Option gewesen wäre (ich sage nicht, dass dies Ihr Fall ist). Und sicherheitstechnisch vergisst man oft, was seine / ihre Hauptanliegen sein sollten.
Peterph

2

Ich habe versucht, dieses Problem zu lösen, als ich Schlüsselpaare generiert und mit Python in einer Datenbank gespeichert habe. Im Folgenden sind einige der Schritte aufgeführt, die ich letztendlich ausgeführt habe, nämlich das Starten ssh-agentund Interagieren damit. Es ist in Python, aber vermutlich können Sie es in alles andere übersetzen. Ein weiteres Merkmal ist, dass keines dieser Elemente verwendet wird shell=True, sodass sie vor Injektionsangriffen sicherer sind.

import subprocess
import os
sockfile = '/some/place.sock'

agent = subprocess.Popen(['ssh-agent',
          '-D', # foreground mode
          '-a', sockfile, # bind address (socket file)
     ])
subprocess.check_call(['ssh-add', 
           '-D', # delete all identities from the agent
      ], 
      env={'SSH_AUTH_SOCK': sockfile},
)

Das löst ein ssh-agentProgramm aus, das nur für unser Programm bestimmt ist, und löscht es (ich glaube, es lädt meine Benutzerschlüssel hinein, bin mir aber nicht sicher). Die Umgebungsvariable, die SSH_AUTH_SOCKnormalerweise von festgelegt wird ssh-agent(aber die wir manuell erstellt haben), geben wir an andere weiter Programme.

Als nächstes geben wir ssh-addihm den privaten Schlüssel (hier wird er dr.private_keyals Zeichenfolge gespeichert , aber ich muss ihn serialisieren, damit ich ihn als ASCII codiere).

adder = subprocess.Popen(['ssh-add', 
        '-', # read key from stdin
     ], 
     env={'SSH_AUTH_SOCK': sockfile}, 
     stdin=subprocess.PIPE,
)
adder.communicate(dr.private_key.encode('ascii'))
retval = adder.wait()
assert retval == 0 # added successfully

Wenn ich jetzt eine SSH-verwendende Anwendung verwende, z. B. Git, beziehe ich mich darauf, denselben SSH-Agent-Socket zu verwenden:

gitp = subprocess.Popen(
        ['git', '-C', os.path.abspath('../some-repo') ,'fetch'], 
        env={'SSH_AUTH_SOCK': sockfile}, 
        stdout=subprocess.PIPE, 
        stderr=subprocess.STDOUT,
    )
print(gitp.communicate()[0].decode('ascii'))

und es funktioniert gut. Die einzige "temporäre Datei" ist der Socket, der von verwendet wird. Sie ssh-agentwird jedoch erstellt, sodass nur der Eigentümer über Berechtigungen verfügt. Sie wird entfernt, wenn Sie den Agenten beenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.