BLOG | NGINX

Sichere Verteilung von SSL-Private-Keys mit NGINX

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Owen Garrett Miniaturbild
Owen Garrett
Veröffentlicht am 02. April 2019

Dieser Blogbeitrag beschreibt mehrere Methoden zur sicheren Verteilung der privaten SSL-Schlüssel, die NGINX beim Hosten SSL-verschlüsselter Websites verwendet. Darin wird erklärt:

Für viele Bereitstellungen ist der Standardansatz ausreichend. Die beiden ausgefeilteren Ansätze, die in diesem Beitrag besprochen werden, blockieren andere Möglichkeiten, wie ein Angreifer an private SSL-Schlüssel gelangen kann. In den Folgebeiträgen werden wir uns noch ein paar weitere Techniken ansehen:

  • Verwenden von geheimen Speichern von Drittanbietern wie HashiCorp Vault zur sicheren Verteilung von Passwörtern
  • Automatisierung der Bereitstellung von Zertifikaten aus Vault in den Schlüssel-Wert-Speicher von NGINX Plus, sodass private Schlüsseldaten nie auf der Festplatte gespeichert werden

Die in diesem Beitrag vorgestellten Ansätze gelten für Benutzer, die ihre eigenen Schlüssel verwalten und ihre eigene sichere Schlüsselverteilungsstrategie erstellen müssen. Sie sind nicht erforderlich für Benutzer, die NGINX in Umgebungen ausführen, die bereits in einen geheimen Speicher integriert sind, wie z. B. Kubernetes .

Dieser Beitrag gilt sowohl für NGINX Open Source als auch für NGINX Plus. Der Einfachheit halber beziehen wir uns durchgehend auf NGINX .

Herausgeber – Dieser Beitrag ist der erste einer Reihe über die Sicherung privater SSL-Schlüssel in NGINX. Siehe auch die anderen Beiträge der Reihe:

 

Warum den privaten SSL-Schlüssel schützen?

SSL/TLS wird zur Authentifizierung, Verschlüsselung und Überprüfung der Integrität von Netzwerktransaktionen verwendet. Websites authentifizieren sich mithilfe eines öffentlichen Zertifikats, das von einer Zertifizierungsstelle (Certificate Authority, CA) signiert wurde, und weisen den Besitz des Zertifikats nach, indem sie Berechnungen mit dem entsprechenden privaten Schlüssel (der geheim gehalten werden muss) durchführen.

Wenn der private Schlüssel kompromittiert wird (einer anderen Entität offengelegt wird), bestehen zwei Hauptrisiken.

  • Risiko 1: Identitätsdiebstahl . Ein Angreifer, der über den privaten Schlüssel verfügt, kann den Netzwerkverkehr abfangen und dann einen Man-in-the-Middle -Angriff (MITM) starten. Bei diesem Angriff wird der gesamte Datenverkehr erfasst, entschlüsselt und möglicherweise auch verändert, ohne dass die Clients oder die Website davon Kenntnis haben.
  • Risiko 2: Entschlüsselung . Ein Angreifer, der über den privaten Schlüssel verfügt und den Netzwerkverkehr aufgezeichnet hat, kann den Netzwerkverkehr dann offline entschlüsseln. Beachten Sie, dass dieser Angriff nicht gegen Verbindungen verwendet werden kann, die eine Perfect Forward Secrecy (PFS)-Verschlüsselung verwenden.

Wenn der private Schlüssel kompromittiert wurde, besteht Ihre einzige Möglichkeit darin, sich an die Zertifizierungsstelle zu wenden und die Sperrung Ihres Zertifikats zu beantragen. Sie müssen sich dann darauf verlassen, dass die Clients den Sperrstatus prüfen und respektieren.

Darüber hinaus empfiehlt es sich, Zertifikate mit kurzen Ablaufzeiten zu verwenden (Zertifikate von Let’s Encrypt laufen beispielsweise nach 90 Tagen ab). Kurz bevor ein Zertifikat abläuft, müssen Sie einen neuen privaten Schlüssel generieren und ein neues Zertifikat von der Zertifizierungsstelle erhalten. Dadurch wird Ihr Risiko verringert, falls der private Schlüssel kompromittiert wird.

Die NGINX-Sicherheitsgrenze

Welche Personen und Prozesse können in NGINX auf private SSL-Schlüssel zugreifen?

Zunächst einmal kann jeder Benutzer, der Root- Zugriff auf den Server erhält, auf dem NGINX läuft, alle Ressourcen lesen und verwenden, die NGINX selbst verwendet. Beispielsweise gibt es bekannte Methoden, um den privaten SSL-Schlüssel aus dem Speicher eines laufenden Prozesses zu extrahieren.

Daher ist es unabhängig davon, wie der private Schlüssel gespeichert und verteilt wird, nicht möglich, den privaten Schlüssel vor einem Angreifer mit Root- Rechten auf dem Hostserver zu schützen.

Darüber hinaus kann jeder Benutzer, der die NGINX-Konfiguration ändern und festschreiben kann, diese Befugnis auf viele Arten nutzen – um den Proxy-Zugriff auf interne Dienste zu öffnen, Authentifizierungsmaßnahmen zu umgehen usw. Er oder sie kann die NGINX-Konfiguration ändern, um Root- Zugriff (oder gleichwertigen Zugriff) auf den Server zu erhalten, obwohl Tools wie SELinux und AppArmor helfen, diese Möglichkeit einzudämmen.

Daher ist es im Allgemeinen nicht möglich, den privaten Schlüssel vor einem Angreifer zu schützen, der die NGINX-Konfiguration ändern und festschreiben kann.

Glücklicherweise verfügt jede kompetente Organisation über solide Sicherheitsprozesse, die es einem Angreifer schwer machen, Root -Rechte zu erlangen oder die NGINX-Konfiguration zu ändern.

Es gibt jedoch zwei weitere Möglichkeiten, wie ein Angreifer mit weniger Privilegien Zugriff auf den privaten Schlüssel erhalten könnte:

  • Ein Benutzer muss möglicherweise aus legitimen Gründen die NGINX-Konfiguration anzeigen oder möchte Zugriff auf eine Konfigurationsdatenbank oder ein Backup erhalten. Private NGINX-Schlüssel werden normalerweise in der Konfiguration gespeichert.
  • Ein Benutzer könnte Zugriff auf das Dateisystem des NGINX-Servers erhalten, möglicherweise über einen Hypervisor oder ein System-Backup. Auf alle im Dateisystem gespeicherten Daten, einschließlich des privaten Schlüsselmaterials, kann potenziell zugegriffen werden.

Die in diesem Dokument beschriebenen Prozesse versiegeln diese beiden Angriffsmethoden.

Standard-NGINX-Konfiguration

Wir beginnen mit einem Blick darauf, wie eine typische NGINX-Konfiguration mit SSL/TLS aussieht:

Server { listen 443 ssl; Servername a.dev0; SSL-Zertifikat ssl/a.dev0.crt; SSL-Zertifikatsschlüssel ssl/a.dev0.key; Standort / { return 200 "Hallo von Dienst A\n"; } }

Das öffentliche SSL-Zertifikat ( a.dev0.crt ) und der private Schlüssel ( a.dev0.key ) werden im Dateisystem unter /etc/nginx/ssl/ gespeichert. Der private Schlüssel wird nur vom NGINX-Masterprozess gelesen, der normalerweise als Root ausgeführt wird. Daher können Sie für ihn die strengstmöglichen Zugriffsberechtigungen festlegen:

root@web1:/etc/nginx/ssl# ls -l a.dev0.key -r-------- 1 root root 1766 15. Aug. 16:32 a.dev0.key

Der private Schlüssel muss jederzeit verfügbar sein; der NGINX-Masterprozess liest ihn bei jedem Start der NGINX-Software, beim Neuladen der Konfiguration oder bei einer Syntaxprüfung ( nginx -t ).

Weitere Informationen zum Konfigurieren von SSL/TLS finden Sie im NGINX Plus-Administratorhandbuch .

Sicherheitsimplikationen der Standardkonfiguration

Wie oben erwähnt, kann der private SSL-Schlüssel von einem Angreifer gelesen werden, der Root- Zugriff auf den laufenden Container, die virtuelle Maschine oder den Server erhält, auf dem die NGINX-Software ausgeführt wird.

Verschlüsseln privater SSL-Schlüssel

NGINX unterstützt verschlüsselte private Schlüssel unter Verwendung sicherer Algorithmen wie AES256:

root@web1:/etc/nginx/ssl# mv a.dev0.key a.dev0.key.plain root@web1:/etc/nginx/ssl# openssl rsa -aes256 -in a.dev0.key.plain -out a.dev0.key writing RSA key Geben Sie die PEM-Passphrase ein: sicheres Passwort Überprüfen - Geben Sie die PEM-Passphrase erneut ein: sicheres Passwort

Wenn Sie dann NGINX starten oder die NGINX-Konfiguration neu laden oder testen, fordert NGINX das Entschlüsselungskennwort interaktiv an:

root@web1:/etc/nginx# nginx -t Geben Sie die PEM-Passphrase ein: sicheres Passwort nginx: Die Syntax der Konfigurationsdatei /etc/nginx/nginx.conf ist in Ordnung nginx: Der Test der Konfigurationsdatei /etc/nginx/nginx.conf war erfolgreich

Verwenden einer SSL-Passwortdatei

Die interaktive Eingabe von Passwörtern ist umständlich und lässt sich nur schwer automatisieren. Sie können NGINX jedoch so konfigurieren, dass eine Liste von Passwörtern verwendet wird, die in einer separaten Datei mit dem Namen ssl_password_file gespeichert sind. Wenn NGINX einen privaten Schlüssel lesen muss, versucht es, den Schlüssel nacheinander mit jedem der Passwörter in der Datei zu entschlüsseln. Wenn keines der Passwörter gültig ist, verweigert NGINX den Start.

SSL-Passwortdatei /var/lib/nginx/ssl_passwords.txt;

Die SSL-Passwortdatei muss getrennt von der Konfiguration verteilt werden und darf nur vom Root -Benutzer gelesen werden können. Sie können es als Autorisierungstoken betrachten, der auf vertrauenswürdigen Servern platziert wird. NGINX kann die privaten Schlüssel nur entschlüsseln, wenn es auf einem Server mit dem Autorisierungstoken ausgeführt wird.

Sicherheitsauswirkungen von verschlüsselten Schlüsseln in einer separaten Datei

Diese Methode reduziert die Angriffsfläche, indem sie die NGINX-Konfiguration allein für einen Angreifer nutzlos macht. Der Angreifer muss außerdem den Inhalt der SSL-Passwortdatei abrufen.

Wenn ein Angreifer Root- Zugriff auf das Dateisystem erhält, in dem die SSL-Passwortdatei gespeichert ist (beispielsweise aus einer Sicherung oder über das Hostsystem), kann er die Datei lesen und die Passwörter zum Entschlüsseln privater SSL-Schlüssel verwenden.

Sie können dieses Risiko verringern, indem Sie die SSL-Passwortdatei auf einer RAM-Disk oder einem tmpfs speichern. Dieser Speicher ist für externe Angreifer im Allgemeinen weniger zugänglich (er wird beispielsweise beim Neustart des Servers gelöscht) und kann von Systemsicherungen ausgeschlossen werden. Sie müssen sicherstellen, dass die Kennwortdatei beim Systemstart initialisiert wird.

SSL-Passwortlisten sicherer verteilen

Das folgende Verfahren beschreibt eine sicherere Möglichkeit zum Verteilen von Listen mit SSL-Passwörtern von einem zentralen Verteilungspunkt aus.

Wenn NGINX einen SSL-Schlüssel entschlüsseln muss, fragt es den zentralen Verteilungspunkt ab und verwendet die Passwörter, ohne sie jemals auf der lokalen Festplatte zu speichern. Zur Authentifizierung gegenüber dem zentralen Passwort-Server verwendet die NGINX-Instanz einen Token, welchen Sie jederzeit widerrufen können, um den Zugriff auf die Passwörter zu sperren.

Erstellen eines zentralen Kennwortverteilungspunkts

Beginnen Sie mit der Erstellung eines Kennwortverteilungspunkts (PDP). Für diese einfache Implementierung verwenden wir einen HTTPS-Dienst, um die Kennwortliste bereitzustellen, authentifiziert durch Benutzername und Kennwort:

$ curl -u dev0:mypassword https://pdpserver.local/ssl_passwords.txt Passwort1 Passwort2 …

Sie können dann den Zugriff aktivieren oder widerrufen, indem Sie nach Bedarf Authentifizierungstoken am PDP hinzufügen oder entfernen. Sie können den Kennwortverteilungsserver mithilfe eines Webservers wie NGINX implementieren und die jeweils geeigneten Authentifizierungstoken verwenden.

Als Nächstes müssen wir NGINX einrichten, um die Passwörter vom PDP abzurufen. Wir beginnen mit der Erstellung eines Shell-Skripts namens connector.sh mit folgendem Inhalt:

#!/bin/sh
# Verwendung: connector.sh 

CONNECTOR=$1
CREDS=$2
PDP_URL=$3

[ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR

mkfifo $CONNECTOR; chmod 600 $CONNECTOR

while true; do
curl -s -u $CREDS -k $PDP_URL -o $CONNECTOR
done

Das Skript muss als Hintergrundprozess ausgeführt werden und wie folgt aufgerufen werden:

root@web1:~# ./connector.sh /var/run/nginx/ssl_passwords \dev0:meinpassword https://pdpserver.local/ssl_passwords.txt &

Der Connector stellt eine Verbindung zum angegebenen lokalen Pfad ( /var/run/nginx/ssl_passwords ) her und Sie verwenden die Direktive „ssl_password_file“ , um NGINX für den Zugriff auf diesen Pfad zu konfigurieren:

SSL-Passwortdatei /var/run/nginx/ssl_passwords;

Testen Sie den Connector, indem Sie den Connector-Pfad lesen:

root@web1:~# cat /var/run/nginx/ssl_passwords Passwort1 Passwort2 …

Überprüfen Sie, ob NGINX das Kennwort lesen und die SSL-Schlüssel entschlüsseln kann:

root@web1:~# nginx -t nginx: die Syntax der Konfigurationsdatei /etc/nginx/nginx.conf ist in Ordnung nginx: Der Test der Konfigurationsdatei /etc/nginx/nginx.conf war erfolgreich

Mit dem zentralen PDP-Ansatz können Sie alle Ressourcen, die NGINX normalerweise von der Festplatte liest, sicher verteilen, beispielsweise einzelne private Schlüssel oder andere vertrauliche Daten.

Sicherheitsimplikationen eines PDP

Diese Lösung bietet im Vergleich zur Speicherung von SSL-Passwörtern auf der Festplatte mehrere Vorteile:

  • Die SSL-Passwörter werden niemals im Dateisystem des Servers gespeichert , sodass ein Angreifer mit Zugriff auf das Dateisystem nicht direkt darauf zugreifen kann.
  • Die Verteilung der Passwörter erfolgt über einen zentralen Zugriffspunkt , was die Überwachung und Prüfung vereinfacht.
  • Der Zugriff auf einzelne Server kann zentral gesteuert werden . Wenn beispielsweise ein Server außer Betrieb genommen wird, widerrufen Sie seinen Zugriffstoken.

Beachten Sie, dass ein Benutzer mit Zugriff auf das Dateisystem möglicherweise die für den Zugriff auf den PDP verwendeten Anmeldeinformationen extrahieren kann. Es ist wichtig, diese Anmeldeinformationen zu widerrufen, wenn sie nicht mehr benötigt werden.

Zusammenfassung

Es gibt viele Möglichkeiten, private SSL-Schlüssel vor der Offenlegung zu schützen, wobei die Sicherheitsstufe und Komplexität zunimmt:

  • Für die große Mehrheit der Organisationen ist es ausreichend, den Zugriff auf die Umgebungen, in denen NGINX ausgeführt wird, einzuschränken, sodass nicht autorisierte Benutzer keinen Root- Zugriff erhalten und die NGINX-Konfiguration nicht einsehen können.
  • In einigen Umgebungen ist es möglicherweise nicht möglich, den Zugriff auf die NGINX-Konfiguration vollständig einzuschränken. Daher kann eine SSL-Kennwortdatei verwendet werden.
  • In bestimmten Fällen möchten Organisationen möglicherweise sicherstellen, dass Schlüssel und Passwörter niemals auf der Festplatte gespeichert werden. Der Kennwortverteilungspunktprozess stellt einen Proof of Concept für diese Lösung dar.

In den anderen Beiträgen dieser Reihe werden weitere Schritte beschrieben, die Sie zum Sichern von SSL-Schlüsseln unternehmen können:

Probieren Sie NGINX Plus selbst aus – starten Sie noch heute Ihre kostenlose 30-Tage-Testversion oder kontaktieren Sie uns, um Ihre Anwendungsfälle zu besprechen .


„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."