Absichern von Truststores und Keystores

Hin und wieder erlebe ich es persönlich oder lese davon, dass jemand die Frage stellt, wie kryptographische Geheimnisse gesichert werden können. Ich gebe hier mal einen Anstoß, darüber aus der Sicht der Software-Architektur auf Systemebene nachzudenken...

Problembeschreibung

Kurz gesagt geht es darum, dass kryptographische Geheimnisse auf einem Computersystem so gesichert sein müssen, dass sie nicht manipuliert und/oder abgelauscht werden können.

Reden wir von Digitalen Identitäten, die aus öffentlichem und privaten Schlüssel zusammen mit dem elektronischen Zertifikat bestehen, so dürfen diese - speziell der private Schlüssel - nicht in die Hände eines Angreifers gelangen. Der Keystore, der diese drei zusammengehörigen Entitäten enthält - bzw. dessen Inhalt - darf also nicht in die Hände eines Angreifers gelangen. Und natürlich muss es für Unbefugte unmöglich sein, seinen Inhalt zu ersetzen.

Wenn man mit anderen Entitäten kommunizieren möchte ist es wichtig, zu wissen, ob der jeweilige Gegenüber auch tatsächlich derjenige ist, mit dem man erwartet, Informationen auszutauschen. Die Authentizität des Verfassers lässt sich mittels seiner elektronischen Unterschrift verifizieren, die mit seinem elektronischen Zertifikat abgesichert ist - die Riege derjenigen, die elektronische Zertifikate erstellen, denen ich vertraue ist über deren Zertifikate im Truststore abgebildet - Es ist also sehr wichtig, dass dieser Truststore nicht beliebig von einem Angreifer manipuliert werden kann.

Konzept

Sehr oft, wenn die eingangs erwähnte Frage gestellt wird, erfolgt reflexhaft die Antwort: "Nutze ein TPM". Ich möchte hier aufzeigen, dass es durchaus möglich ist, Truststore und Keystore über ein geeignetes Systemarchitekturkonzept auch als Dateien ausreichend abzusichern.

Ich werde dazu auf diverse "Stilmittel" zurückgreifen, die - konsequent angewendet - helfen, die oben genannten Ziele zu erreichen:

  • dedizierte Nutzer und Gruppen für einzelne Prozesse und Gruppen
  • An das Problem angepasstes Rollen- und Rechtekonzept
  • Deaktivieren des Root-Nutzerkontos
  • Massenspeicherverschlüsselung
  • Einschränkung interaktiver Shells
  • Genaue Definition von Aufgaben des Superusers
  • Administrative Aufgaben nur mittels Multifaktor Authentifizierung

Härtung des Systems

Dazu sind zunächst einige Aufgaben durchzuführen, die allgemeiner Natur sind und auch für andere Lösungen die Grundlage einer Systemimplementierung bilden sollten:

Sämtliche Massendatenträger sind zu verschlüsseln. Diese Maßnahme hilft, den Zugriff auf und die Manipulation von sensiblen Daten zu verhindern, nachdem der Massendatenträger aus dem Gerät ausgebaut wurde oder auf dem Gerät ein alternatives Betriebssystem gestartet wurde, das die Rollen und Rechte und die Zugriffsbeschränkungen (siehe unten) auf die sensiblen Daten aushebeln könnte.

Das Root-Konto muss deaktiviert werden - da der Nutzer root alle Dateien auf dem System lesen und schreiben darf ist mit einem erfolgreichen Angriff - zum Beispiel per social Engineering oder durch klassische Privilege escalation ebenfalls wieder der Schutz durch Vergabe restriktiver Zugriffsrechte auf Nutzer und Gruppenbasis gefährdet.

Administrative Aufgaben müssen definiert werden und es muss sichergestellt werden, dass nur diese definierten Aufgaben durch ein entsprechend höherprivilegiertes Nutzerkonto ausgeführt werden dürfen. Dies kann zum Beispiel mittels entsprechender Regeln für sudo realisiert werden.

Für jede Anwendung/jeden Prozess müssen eigene Nutzer angelegt werden, die den jeweiligen Prozess/die Anwendung ausführen. Diese Nutzerkonten dürfen keine interaktiven Shells nutzen.

Das einzige Konto, das administrative Aufgaben wahrnehmen darf, muss über eine Multifaktor-Authentifizierung verfügen, die sich nicht umgehen lassen darf und diesen Namen auch wirklich verdient.

Rollen und Rechte

Wir gehen hier von einer Anwendung aus, die einen bestimmten intended Use umsetzt und dafür die Unterstützung kryptographischer Primitiven benötigt. Dazu ist zunächst nur lesender Zugriff auf diese Primitiven notwendig.

Damit könnte man also beginnen, die entsprechenden Dateien, die Truststore und Keystore darstellen, mit restriktiven Zugriffsrechten zu schützen, die nur dem Eigentüner - genennt AppUser - Leserechte einräumen und sonst niemandem.

Allerdings ist es auch hin und wieder nötig, diese Dateien ändern zu können: Zertifikate werden erneuert, und die Vertrauensstellung der Zertifikate im Truststore kann sich ändern - neue Trust-Anchors können dazukommen. Es muss also möglich sein, unter eng definierten Rahmenbedingungen diese Dateien auch zu ändern.

Für dieses Szenario legen wir ein weiteres Nutzerkonto an, das eine administrative Anwendung ausführen kann, die genau diese administrativen Aufgaben implementiert. Dieses Konto - nennen wir es CryptoAdmin" - ist nunmehr der Eigentümer der Dateien. Beide Nutzer - AppUser und CryptoAdmin - gehören einer Gruppe AppAccounts an und die Rechte werden so festgelegt, dass der Eigentümer Schreib- und Leserechte auf die Dateien hat und die Gruppe lediglich Leserechte.

Damit ist der Schutz für unsere gefährdeten Assets bereits deutlich höher als in einer Anwendung, die ohne dedizierten Nutzer gewöhliche und administrative Aufgaben mischt. Die Architektur stellt sich wie folgt dar:

Compartmentalization

Bisher habe ich davon geschrieben, dass ich die eigentliche Anwendung und die Administration der Trust- und Keystores in getrennten Prozessen halten würde, die wiederum unterschiedlichen Nutzerkonten gehören und in deren Kontext ausgeführt werden.

Wenn man aber über Threat Modeling und Trust Boundaries nachdenkt und über Open-Source- und andere Third-Party-Komponenten, so erkennt man, dass es richtiger wäre, die sensiblen Operationen irgendwie in einem speziellen, sicheren Kontext auszuführen. DAs würde es zum Beispiel verhindern, dass die Ausnutzung einer Sicherheitslücke in einer der in der App verwendeten Komponenten die Crypto-Operationen kompromittieren könnte.

Mein Vorschlag dafür ist radikale Trennung: Ich schlage vor, die App in zwei Teile aufzuspalten, die mittels (zum Beispiel) Named Pipes kommunizieren: Die App selbst bleibt mit allen Funktionalitäten erhalten. Nur für Crypto-Operationen wie Signieren oder Entschlüsseln empfangener Daten greift sie auf die Unterstützung eines neuen Prozesses zurück, den ich hier schlicht SW HSM nennen werde. Dieser Prozess hat lediglich ein Bitstrom-Interface: Für jede cryptographische Operation bietet er eine named Pipe an, über die die Input-Daten an ihn gesendet werden und über den er das Ergebnis zurückliefert.

Damit ist eine saubere Trennung erreicht - im Prozess SW HSM sind fast keine Sicherheitslücken zu erwarten: Das Interface basiert auf reinen Bitströmen - das bedeutet, dass weder beim Parsen noch beim Validieren der Daten Lücken ausgenutzt werden können. Sicherheitslücken in den Komponenten der App können SW HSM nicht gefährlich werden und es ist nur für autorisierte Nutzer möglich, Daten in die Pipes zu schreiben und aus ihnen zu lesen.

Durch die Einführung eines weiteren Prozesses ist es nötig, das Rollen- und Rechtekonzept etwas zu erweitern, wie im nachstenden Bild gezeigt:

Idealerweise ist SW HSM so zu konfigurieren, dass nur die Crypto-Funktionalitäten aktiv sind, die App wirklich nutzt. Man kann darüber auch TLS-Verbindungen realisieren - sowohl als Client als auch im Server-Modus. Wie oben bereits gesagt muss beim Aufsetzen des Systems die entsprechenden Named Pipes angelegt werden. Die crypto-Operationen, die ein solches SW HSM realisieren kann sind:

  • Entschlüsseln
  • Signieren
  • Signatur prüfen
  • TLS Server
  • TLS Client
Es ist noch nicht geplant, aber ich denke darüber nach, eine entsprechende prototypische Implementierung zu erstellen und als OpenSource-Projekt zur Verfügung zu stellen.

Alle Artikel rss Wochenübersicht Monatsübersicht Codeberg Repositories Mastodon Über mich home xmpp


Vor 5 Jahren hier im Blog

  • Demonstration und Beispiele für die Nutzung eines RFC3161-Servers aus Java heraus

    15.05.2021

    Ich habe ein Begleitprojekt zu meiner Implementierung meines Timestamping Server Projekts erstellt: eine Demonstration und ein Beispiel dafür, wie man einen solchen Timestamping-Server von Java aus nutzen kann.

    Weiterlesen

Neueste Artikel

  • Asymmetrische Kryptographie

    Ich habe mich mit der Idee schon länger getragen: Nochmal einen Rundumschlag zu asymmetrischer Kryptographie zu machen. Dabei werde ich mich auf Demonstrationen der einzelnen Konzepte und Operationen mit Beispielcode konzentrieren und zu jedem der vorgestellten Konzepte mehr oder weniger ausführlich bezüglich der Einsatzszenarien und Vor- und Nachteile Stellung beziehen

    Weiterlesen
  • Futro-Thin-Clients und PCI Express Mini Cards

    Ich habe mich von einigen Artikeln anderer Besitzer und Upcycler von Futro-Thin-Clients inspirieren lassen - das hat dazu geführt, dass ich von meinem eigentlichen Projekt (Bauen eines kleinen Clusters) abgekommen bin und die Hardware ein wenig genauer unter die Lupe genommen habe...

    Weiterlesen
  • Barbarossa - Stones

    Etwas älteres...

    Weiterlesen

Manche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.

Wer daran teilhaben und eventuell sogar davon profitieren möchte, muss damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.

Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...

PS: Meine öffentlichen Codeberg-Repositories findet man hier.