Sicherheitsvorfälle verringern


In diesem Dokument werden häufig ergriffene Maßnahmen zur Schadensbegrenzung und gängige Reaktionen auf potenzielle Sicherheitsvorfälle in Ihren GKE-Clustern (Google Kubernetes Engine) und -Containern beschrieben.

Die Vorschläge in Sicherheit von Clustern erhöhen können die Sicherheit Ihrer GKE-Arbeitslasten verbessern. Sicherheitsvorfälle können jedoch auch dann auftreten, wenn Maßnahmen zum Schutz Ihrer Arbeitslasten praktiziert werden.

Vorfälle erkennen

Damit potenzielle Vorfälle erkannt werden, sollten Sie einen Prozess einrichten, der die Logs Ihrer Arbeitslast erfasst und überwacht. Richten Sie dann Benachrichtigungen ein, die durch in Logs erkannte abnormale Ereignisse ausgelöst werden. Durch Benachrichtigungen wird Ihr Sicherheitsteam informiert, wenn etwas Ungewöhnliches entdeckt wird. Das Team kann den potenziellen Vorfall dann überprüfen.

Benachrichtigungen aus Logs erstellen

Sie können Benachrichtigungen anhand bestimmter Messwerte oder Aktionen anpassen. Beispielsweise können Benachrichtigungen zu einer hohen CPU-Auslastung auf Ihren GKE-Knoten ein Hinweis darauf sein, dass die Knoten für Kryptomining manipuliert wurden.

Benachrichtigungen sollten dort erzeugt werden, wo Sie Ihre Logs und Messwerte aggregieren. Sie können beispielsweise das Audit-Logging von GKE in Kombination mit logbasierten Benachrichtigungen in Cloud Logging verwenden.

Weitere Informationen zu sicherheitsrelevanten Abfragen finden Sie in der Dokumentation zu Audit-Logging.

Reaktion auf einen Sicherheitsvorfall

Nachdem Sie über einen Vorfall benachrichtigt wurden, ergreifen Sie die erforderlichen Maßnahmen. Beheben Sie die Sicherheitslücke, wenn möglich. Wenn Sie die Ursache der Sicherheitslücke nicht kennen oder noch keine Lösung haben, wenden Sie Maßnahmen zur Schadensbegrenzung an.

Welche Maßnahmen Sie ergreifen können, hängt von der Schwere des Vorfalls ab. Es kommt auch darauf an, wie sicher Sie sind, dass Sie das Problem erkannt haben.

In dieser Anleitung erfahren Sie mehr zu Maßnahmen, die Sie ergreifen können, nachdem Sie einen Vorfall auf einer auf GKE ausgeführten Arbeitslast erkannt haben. Sie könnten so vorgehen, in aufsteigender Reihenfolge des Schweregrades:

  • Snapshot des Laufwerks der Host-VM erstellen. Mithilfe eines Snapshots können Sie einige forensische Untersuchungen zum VM-Status durchführen, der bei der Anomalie aufgetreten ist, nachdem die Arbeitslast neu bereitgestellt oder gelöscht wurde.
  • VM untersuchen, während die Arbeitslast weiterhin ausgeführt wird. Durch die Verbindung mit der Host-VM oder dem Arbeitslastcontainer erhalten Sie unter Umständen Informationen über die Aktionen des Angreifers. Wir empfehlen Ihnen, vor der Untersuchung der Live-VM den Zugriff einzuschränken.

  • Container noch einmal bereitstellen. Durch das erneute Bereitstellen werden aktuell ausgeführte Prozesse im betroffenen Container beendet und neu gestartet.

  • Arbeitslast löschen. Durch das Löschen der Arbeitslast werden derzeit ausgeführte Prozesse im betroffenen Container ohne Neustart beendet.

Diese Maßnahmen zur Schadensbegrenzung werden in den folgenden Abschnitten beschrieben.

Vorbereitung

Die in diesem Thema verwendeten Methoden nutzen die folgenden Informationen:

  • Den Namen der Pods, die Ihrer Meinung nach manipuliert wurden, oder POD_NAME.
  • Den Namen der Host-VM, auf der der Container oder die Pods ausgeführt werden, oder NODE_NAME.

Bevor Sie eine der Aktionen ausführen, sollten Sie nicht außer Acht lassen, dass es zu einer negativen Gegenreaktion des Angreifers kommen könnte, wenn er sich ertappt fühlt. Der Angreifer wird unter Umständen Daten löschen oder Arbeitslasten zerstören. Wenn das Risiko zu hoch ist, sollten Sie drastischere Maßnahmen wie das Löschen einer Arbeitslast ergreifen, bevor Sie weitere Untersuchungen durchführen.

Snapshot des VM-Laufwerks erstellen

Wenn Sie einen Snapshot des VM-Laufwerks erstellen, können Sie eine forensische Untersuchung durchführen, nachdem die Arbeitslast neu bereitgestellt oder gelöscht wurde. Snapshots können erstellt werden, während Laufwerke mit laufenden Instanzen verbunden sind.

  1. Wenn Sie einen Snapshot für Ihren nichtflüchtigen Speicher erstellen möchten, suchen Sie zuerst nach den mit Ihrer VM verbundenen Laufwerken. Führen Sie folgenden Befehl aus und sehen Sie sich das Feld source an:

    gcloud compute instances describe NODE_NAME --zone COMPUTE_ZONE \
        --format="flattened([disks])"
    
  2. Suchen Sie nach den Zeilen, die disks[NUMBER].source enthalten. Die Ausgabe sieht etwa so aus:

    disks[0].source: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/zones/COMPUTE_ZONE/disks/DISK_NAME
    

    Der Laufwerkname ist der Teil des Quellennamens nach dem letzten Schrägstrich. Der Laufwerkname lautet beispielsweise gke-cluster-pool-1-abcdeffff-zgt8.

  3. Führen Sie den folgenden Befehl aus, um den Snapshot abzuschließen:

    gcloud compute disks snapshot DISK_NAME
    

Weitere Informationen finden Sie unter Snapshots von nichtflüchtigem Speicher erstellen in der Compute Engine-Dokumentation.

VM untersuchen, während die Arbeitslast weiterhin ausgeführt wird

Überlegen Sie auch, worauf ein Angreifer Zugriff haben könnte, bevor Sie sich für Maßnahmen entscheiden. Wenn Sie vermuten, dass ein Container manipuliert wurde, und den Angreifer nicht auf sich aufmerksam machen möchten, können Sie eine Verbindung zu dem Container herstellen und ihn untersuchen. Untersuchen Sie den Container also kurz, bevor Sie sich für drastischere Maßnahmen entscheiden. Die Untersuchung ist auch der am wenigsten störende Ansatz für die Arbeitslast, stoppt den Vorfall jedoch nicht.

Alternativ können Sie Ihre Arbeitslasten durch das Einrichten von Live-Forensik-Tools wie GRR Rapid Response, Agents auf Knoten oder Netzwerkfilterung analysieren, um sich nicht auf einem Computer mit privilegierten Anmeldedaten anmelden zu müssen.

Zugriff vor Untersuchung der Live-VM einschränken

Durch Sperrung, Leerung und Beschränkung des Netzwerkzugriffs auf die VM, auf der manipulierte Container gehostet werden, können Sie den manipulierten Container teilweise vom Rest Ihres Clusters isolieren. Dadurch wird das Risiko verringert. Ein Angreifer wird jedoch nicht daran gehindert, sich in Ihrer Umgebung seitlich zu bewegen, wenn er eine kritische Sicherheitslücke ausnutzt.

Knoten sperren und andere Arbeitslasten daraus leeren

Durch das Sperren und Leeren eines Knotens werden Arbeitslasten, die mit dem manipulierten Container verbunden sind, in andere VMs in Ihrem Cluster verschoben. Das macht es schwieriger für einen Angreifer, andere Arbeitslasten auf demselben Knoten zu beeinträchtigen. Es hindert ihn nicht unbedingt daran, den persistenten Status einer Arbeitslast zu prüfen, z. B. durch Überprüfen des Image-Inhaltes des Containers.

  1. Verwenden Sie kubectl, um den Knoten abzusichern und dafür zu sorgen, dass keine anderen Pods darin geplant werden:

    kubectl cordon NODE_NAME
    

    Nach dem Absichern des Knotens sollten Sie andere Pods aus dem Knoten entfernen.

  2. Kennzeichnen Sie den Pod, den Sie in Quarantäne versetzen, mit einem Label:

    kubectl label pods POD_NAME quarantine=true
    

    Ersetzen Sie POD_NAME durch den Namen des Pods, den Sie unter Quarantäne setzen möchten.

  3. Entfernen Sie Pods, die nicht mit quarantine gekennzeichnet sind, aus dem Knoten:

    kubectl drain NODE_NAME --pod-selector='!quarantine'
    

Netzwerkzugriff auf den Knoten beschränken

Wir empfehlen, sowohl den internen als auch den externen Traffic für den Zugriff auf die Host-VM zu sperren. Lassen Sie als Nächstes eingehende Verbindungen von einer bestimmten VM in Ihrem Netzwerk oder Ihrer VPC mit der unter Quarantäne gestellten VM zu.

Der erste Schritt besteht darin, die VM aus der verwalteten Instanzgruppe, der sie gehört, zu verwerfen. Durch das Verwerfen der VM verhindern Sie, dass der Knoten als fehlerhaft gekennzeichnet und automatisch repariert (neu erstellt) wird, bevor die Untersuchung abgeschlossen ist.

Führen Sie den folgenden Befehl aus, um die VM zu verwerfen:

gcloud compute instance-groups managed abandon-instances INSTANCE_GROUP_NAME \
    --instances=NODE_NAME

VM-Firewall einrichten

Durch die Erstellung einer Firewall zwischen dem betroffenen Container und anderen Arbeitslasten im selben Netzwerk wird verhindert, dass ein Angreifer in andere Bereiche Ihrer Umgebung eindringen kann, während Sie mit der weiteren Analyse beschäftigt sind. Da Sie andere Container bereits aus der VM entfernt haben, betrifft dies nur den unter Quarantäne gestellten Container.

Wenn Sie die unten stehende Anleitung zu Firewalls für die VM befolgen, verhindern Sie Folgendes:

  • Neue ausgehende Verbindungen zu anderen VMs in Ihrem Cluster mithilfe einer Regel für ausgehenden Traffic.
  • Eingehende Verbindungen zur manipulierten VM mithilfe einer Regel für eingehenden Traffic.

Führen Sie die folgenden Schritte für den Knoten aus, der den unter Quarantäne zu stellenden Pod hostet, um Ihre anderen Instanzen mit einer ausschließenden Firewallregel für die VM zu schützen:

  1. Weisen Sie der Instanz ein Tag zu, damit Sie eine neue Firewallregel anwenden können.

    gcloud compute instances add-tags NODE_NAME \
        --zone COMPUTE_ZONE \
        --tags quarantine
    
  2. Erstellen Sie eine Firewallregel, um den gesamten ausgehenden TCP-Traffic aus Instanzen mit dem Tag quarantine zu verhindern:

    gcloud compute firewall-rules create quarantine-egress-deny \
        --network NETWORK_NAME \
        --action deny \
        --direction egress \
        --rules tcp \
        --destination-ranges 0.0.0.0/0 \
        --priority 0 \
        --target-tags quarantine
    
  3. Erstellen Sie eine Firewallregel, um den gesamten eingehenden TCP-Traffic an Instanzen mit dem Tag quarantine zu verhindern. Geben Sie dieser Regel für eingehenden Traffic eine priority von 1, damit Sie sie mit einer anderen Regel überschreiben können, die SSH aus einer bestimmten VM zulässt.

    gcloud compute firewall-rules create quarantine-ingress-deny \
        --network NETWORK_NAME \
        --action deny \
        --direction ingress \
        --rules tcp \
        --source-ranges 0.0.0.0/0 \
        --priority 1 \
        --target-tags quarantine
    

Externe IP-Adresse der VM entfernen

Durch das Entfernen der externen IP-Adresse der VM werden alle bestehenden Netzwerkverbindungen außerhalb Ihrer VPC unterbrochen.

Führen Sie die folgenden Schritte aus, um die externe Adresse einer VM zu entfernen.

  1. Suchen und löschen Sie die Zugriffskonfiguration, die die externe IP der VM zuordnet. Suchen Sie zuerst nach der Zugriffskonfiguration. Beschreiben Sie dafür die VM:

    gcloud compute instances describe NODE_NAME \
        --zone COMPUTE_ZONE --format="flattened([networkInterfaces])"
    

    Suchen Sie nach den Zeilen, die name und natIP enthalten. Sie sehen so aus:

    networkInterfaces[0].accessConfigs[0].name:              ACCESS_CONFIG_NAME
    networkInterfaces[0].accessConfigs[0].natIP:             EXTERNAL_IP_ADDRESS
    
  2. Suchen Sie den Wert von natIP, der mit der zu entfernenden externen IP-Adresse übereinstimmt. Notieren Sie sich den Namen der Zugriffskonfiguration.

  3. Führen Sie den folgenden Befehl aus, um die externe IP-Adresse zu entfernen:

    gcloud compute instances delete-access-config NODE_NAME \
        --access-config-name "ACCESS_CONFIG_NAME"
    

SSH-Verbindung zur Host-VM über eine intermediäre VM herstellen

Nachdem Sie die externe IP-Adresse der Host-VM entfernt haben, können Sie keine SSH-Verbindung von außerhalb Ihrer VPC herstellen. Sie greifen von einer anderen VM im selben Netzwerk darauf zu. Für den Rest dieses Abschnitts wird das als intermediäre VM bezeichnet.

Vorbereitung

  • Eine intermediäre VM mit Zugriff auf das Subnetzwerk der Host-VM. Wenn Sie noch keine VM haben, erstellen Sie sie zu diesem Zweck.
  • Die interne IP-Adresse der intermediären VM.
  • Einen öffentlichen SSH-Schlüssel der intermediären VM. Weitere Informationen finden Sie unter SSH-Schlüssel verwalten.

Verbindung zur Host-VM herstellen

  1. Fügen Sie der Host-VM den öffentlichen Schlüssel der intermediären VM hinzu. Weitere Informationen finden Sie in der Compute Engine-Dokumentation unter SSH-Schlüssel hinzufügen und entfernen.
  2. Fügen Sie der intermediären VM ein Tag hinzu.

    gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \
      --zone COMPUTE_ZONE \
      --tags intermediate
    
  3. Fügen Sie eine "ingress allow"-Regel hinzu, um die zuvor hinzugefügte "deny"-Regel zu überschreiben. Führen Sie den folgenden Befehl aus, um die Regel hinzuzufügen.

    gcloud compute firewall-rules create quarantine-ingress-allow \
        --network NETWORK_NAME \
        --action allow \
        --direction ingress \
        --rules tcp:22 \
        --source-tags intermediate \
        --priority 0 \
        --target-tags quarantine
    

    Diese Regel lässt eingehenden Traffic von VMs in Ihrem Netzwerk, die das Tag intermediate haben, auf Port 22 (SSH) zu. Sie überschreibt die "deny"-Regel mit einer priority von 0.

  4. Stellen Sie mithilfe der internen IP-Adresse eine Verbindung zu der unter Quarantäne gestellten VM her:

    ssh -i KEY_PATH USER@QUARANTINED_VM_INTERNAL_IP
    

    Dabei gilt:

    • KEY_PATH: Der Pfad zum privaten SSH-Schlüssel.
    • USER: E-Mail-Adresse Ihres Google Cloud-Kontos.
    • QUARANTINED_VM_INTERNAL_IP: Die interne IP-Adresse.

Container noch einmal bereitstellen

Durch die neue Bereitstellung Ihres Containers starten Sie eine neue Kopie des Containers und löschen den manipulierten.

Sie können einen Container durch Löschen des Pods, der ihn hostet, noch einmal bereitstellen. Wenn der Pod von einem übergeordneten Kubernetes-Konstrukt verwaltet wird, z. B. einem Deployment oder DaemonSet, wird beim Löschen des Pods ein neuer Pod geplant. In diesem Pod werden neue Container ausgeführt.

Die neue Bereitstellung ist in folgenden Fällen sinnvoll:

  • Sie kennen die Ursache der Sicherheitslücke bereits.
  • Sie glauben, dass es einen Angreifer viel Zeit oder Aufwand kosten wird, den Container noch einmal zu manipulieren.
  • Sie glauben, dass der Container schnell wieder manipuliert werden kann, und möchten ihn nicht offline schalten. Daher möchten Sie ihn in einer Sandbox platzieren, um die Auswirkungen zu begrenzen.

Wenn Sie die Arbeitslast neu bereitstellen, sollten Sie gegebenenfalls die Arbeitslast in einer Sandbox-Umgebung wie GKE Sandbox platzieren, wenn das Risiko einer neue Manipulation hoch ist. Durch Sandboxing wird der Zugriff auf den Hostknoten-Kernel begrenzt, wenn der Angreifer den Container wieder manipuliert.

Wenn Sie einen Container noch einmal in Kubernetes bereitstellen möchten, löschen Sie den Pod, in dem er sich befindet:

kubectl delete pods POD_NAME --grace-period=10

Wenn die Container im gelöschten Pod weiterhin ausgeführt werden, können Sie die Arbeitslast löschen.

Folgen Sie der Anleitung unter Isolierung von Arbeitslasten mit GKE Sandbox härten, um den Container in einer Sandbox noch einmal bereitzustellen.

Arbeitslast löschen

Wenn Sie eine Arbeitslast löschen, z. B. ein Deployment oder DaemonSet, werden alle zugehörigen Pods gelöscht. Alle Container in diesen Pods werden dann nicht mehr ausgeführt. Das Löschen einer Arbeitslast kann in folgenden Fällen sinnvoll sein:

  • Sie möchten einen laufenden Angriff stoppen.
  • Sie sind bereit, die Arbeitslast offline zu nehmen.
  • Das sofortige Beenden des Angriffs ist wichtiger als die Verfügbarkeit der Anwendung oder die forensische Analyse.

Verwenden Sie kubectl delete CONTROLLER_TYPE zum Löschen einer Arbeitslast. Führen Sie beispielsweise den folgenden Befehl aus, um ein Deployment zu löschen:

kubectl delete deployments DEPLOYMENT

Wenn durch das Löschen der Arbeitslast nicht alle zugehörigen Pods oder Container gelöscht werden, können Sie sie mithilfe des CLI-Tools der Container-Laufzeit (normalerweise docker) manuell löschen. Verwenden Sie crictl, wenn Ihre Knoten containerd ausführen.

Docker

Wenn Sie einen Container mithilfe der Docker-Container-Laufzeit beenden möchten, können Sie entweder docker stop oder docker kill verwenden.

docker stop stoppt den Container durch Senden eines SIGTERM-Signals an den Stammprozess und wartet 10 Sekunden, bis der Prozess standardmäßig beendet wird. Wenn der Prozess in diesem Zeitraum nicht beendet wurde, wird ein SIGKILL-Signal gesendet. Sie können diesen Kulanzzeitraum mit der Option --time festlegen.

docker stop --time TIME_IN_SECONDS CONTAINER

docker kill ist die schnellste Methode zum Beenden eines Containers. Das Signal SIGKILL wird sofort gesendet.

docker kill CONTAINER

Sie können einen Container auch mit docker rm -f in einem Befehl beenden und entfernen:

docker rm -f CONTAINER

containerd

Wenn Sie die containerd-Laufzeit in GKE verwenden, können Sie Container mit crictl beenden oder entfernen.

Führen Sie den folgenden Befehl aus, um einen Container in containerd zu beenden:

crictl stop CONTAINER

Führen Sie den folgenden Befehl aus, um einen Container in containerd zu entfernen:

crictl rm -f CONTAINER

Host-VM löschen

Wenn Sie den Container nicht löschen oder entfernen können, löschen Sie die virtuelle Maschine, die den betroffenen Container hostet.

Wenn der Pod weiterhin sichtbar ist, können Sie den Namen der Host-VM mit dem folgenden Befehl feststellen:

kubectl get pods --all-namespaces \
  -o=custom-columns=POD_NAME:.metadata.name,INSTANCE_NAME:.spec.nodeName \
  --field-selector=metadata.name=POD_NAME

Führen Sie den folgenden gcloud-Befehl aus, um die Host-VM zu löschen:

gcloud compute instance-groups managed delete-instances INSTANCE_GROUP_NAME \
    --instances=NODE_NAME

Wenn Sie die Instanz aus der verwalteten Instanzgruppe entfernen, reduziert sich die Größe der Gruppe um eine VM. Sie können eine Instanz mit dem folgenden Befehl manuell wieder zur Gruppe hinzufügen:

gcloud compute instance-groups managed resize INSTANCE_GROUP_NAME \
    --size=SIZE

Nächste Schritte