So gestalten Sie die Container-Entwicklung sicher
Softwareentwicklung in Container-Umgebungen stellt Unternehmen vor neue SecurityHerausforderungen. Erfahren Sie, welche Sicherheitsmaßnahmen Ihr IT-Team umsetzen sollte.
Container erleichtern es, Anwendungen und Microservices zu programmieren, zu testen, auszurollen und zu verwalten. Allerdings vergrößert die Technik die Angriffsfläche auf Unternehmen. Während der Entwicklung wie auch bei der Integration und Bereitstellung sowie im laufenden Betrieb gilt es, Risiken zu minimieren. Das bezieht sich auf die Container selbst, verwendete Orchestrierungs-Tools wie Kubernetes und die zugrunde liegende Infrastruktur.
>> Die Gefahren <<
Container sind durch dieselben Risiken wie andere virtualisierte Umgebungen bedroht. Gary Duan, CTO von Kubernetes-Spezialist NeuVector, nennt folgende Sicherheitsprobleme: DDoS-Attacken auf Anwendungsebene und (XSS-)Angriffe auf öffentliche Container; kompromittierte Container, die zusätzliche Malware herunterladen oder interne Systeme nach Schwachstellen und sensiblen Daten scannen; Container-Breakouts, die die Isolationsschicht des Containers überwinden, um unautorisierten Zugriff auf andere Container, Host-Systeme oder Rechenzentren zu bekommen; Mechanismen, die den Container zwingen, viele Systemressourcen zu verbrauchen, um die Performance anderer Container zu verringern oder einen Crash zu provozieren; Live-Patches für Anwendungen, um schädliche Prozesse einzuführen.
Zudem gibt es Lücken in Kommunikationsprotokollen, die auch im Zusammenhang mit Containern verwendet werden. Zum Beispiel gelang es Forschern, die Verschlüsselung der Version 1.3 des Transport-Layer-Security(TLS-)Protokolls mit Hilfe eines BleichenbacherAngriffs zu knacken. Des Weiteren werden regelmäßig Schwachstellen in der Verwaltungssoftware Kubernetes entdeckt. So konnten Angreifer über die Sicherheitslücke „CVE2018-1002105“Zugriff auf den API-Server der Software erhalten und sich so weitreichende
Administratorrechte über Container-Cluster verschaffen. Wenige Monate danach wurde mit „CVE-2019-5736“eine ähnliche Anfälligkeit bekannt. Um sich gegen diese Risiken abzusichern, können sich IT-Teams an den drei Phasen des Container-Lebenszyklus orientieren: Aufbau, Bereitstellung und Betrieb.
>> Aufbauphase <<
Während der Softwareentwicklung geht es nach Ausführungen des IT-Sicherheitsspezialisten Palo Alto Networks zuerst darum, festzulegen, wie der gewünschte Endzustand aussehen soll. Das bedeute, sich auf die Beseitigung von Schwachstellen, Malware und unsicherem Code zu konzentrieren. Hierzu sei es wichtig, dass Unternehmen ein offizielles Container-Register einrichteten.
Ein solches Container-Register ist dazu da, vertrauenswürdige Images zu erstellen. Es gilt, einen Prozess festzulegen und automatisiert durchzusetzen, der verhindert, dass Container aus einer nicht vertrauenswürdigen Registry bereitgestellt werden. Dabei ist zu beachten, dass viele populäre Images beispielsweise in der Docker Hub Registry nur Root-Benutzer angeben. Viele Docker-Image-Autoren versäumen es, den Root-Zugriff zu unterbinden. Die Docker-Engine führt diese Container dann standardmäßig als Root aus, was Angreifern ermöglicht, großen Schaden anzurichten. Über denselben Weg sind auch Attacken denkbar, die „Docker Image Poisoning“über bösartige Docker-Images von Drittanbietern ausnutzen, die in den Unternehmensservices eingebaut wurden. Zwar ist dieser Exploit noch nicht verbreitet, aber der Cloud-Sicherheitsanbieter Redlock hat gezeigt, dass er möglich ist.
Als Kriterium für vertrauenswürdige Images nennt Red Hat deren Signatur. Mit „Docker Content Trust“können Autoren ihre hochgeladenen Images signieren. Bei deren Download verifiziert die lokale Docker-Installation des Nutzers die Signatur und stellt so sicher, dass das Image aktuell ist und nicht manipuliert wurde. Zudem sollte das IT-Team sich folgende Fragen stellen: Sind Runtime- und BetriebssystemSchichten des Containers aktuell? Wie schnell und häufig werden die Container durch den Autor aktualisiert? Wird auf bekannte Probleme hin überwacht, und wenn ja, wie?
>> Bereitstellung <<
Beim Deployment geht es um die korrekte Zusammenstellung der Container. Images, die selbst zwar keine Schwachstelle haben, aber in einem unsicher konfigurierten KubernetesPod bereitgestellt werden, bleiben gefährdet. Ein Pod ist eine Gruppe aus einem oder mehreren Containern mit gemeinsamem Speicher und Netz sowie einem Regelwerk, wie die Container ausgeführt werden.
Für eine sichere Konfiguration sollten Sicherheitsstandards für die Orchestrierung und die Container-Engine erarbeitet und umgesetzt werden. Anhaltspunkte dafür liefern beispielsweise die Benchmarks für Docker und Kubernetes des Center for Internet Security (CIS). Damit lässt sich unter anderem der Zugriff von außen regulieren und verhindern, dass beispielsweise Traffic zu Kubernetes-Pods aus jeder Quelle akzeptiert wird.
Red Hat rät, eine private Registry zu verwenden, um den Zugriff auf die Images, die das Team verwendet, zu verwalten. Nur nach Schwachstellen gescannte und geprüfte Images sollten in dieses Verzeichnis aufgenommen werden. Über rollenbasierte Zuweisungen lässt sich der Zugang kontrollieren. Die Registry ermöglicht es, Richtlinien für gespeicherte Container-Images zu automatisieren und zuzuweisen, um menschliche Fehler zu vermeiden. Zudem besteht die Möglichkeit, Inhalte wie Image-Metadaten zu verwalten. Die folgenden Fragen sollten in diesem Zusammenhang beantwortet werden: Welche rollenbasierten Kontrollen können für das Management von Container Images genutzt werden? Lassen sich Images über Tagging- oder Kennzeichnungsfunktionen sortieren? Können Images separat für Entwicklung, Prüfung und Produktion als genehmigt gekennzeichnet werden? Bietet die Registry sichtbare Metadaten, um bekannte Schwachstellen zu erkennen? Lässt die Zugriffsverwaltung zu, Richtlinien zuzuweisen und zu automatisieren, beispielsweise um Signaturen zu prüfen oder Scans zu codieren?
>>Betrieb<<
Während des Betriebs gilt es auch, neue Lücken in laufenden Containern zu finden. Darunter fallen ungewöhnliche Aktivitäten, die auf eine Zero-Day-Schwachstelle deuten. Dazu ist es wichtig, einen Normalzustand zu definieren, anhand dessen Abweichungen festgestellt werden können. Laut Palo Alto Networks gestaltet sich die Sicherheit im Betrieb weniger komplex, wenn das Security-Team nicht erst hinzugezogen wird, wenn der Container fertiggestellt ist, sondern im Sinne des Security-byDesign-Prinzips bereits in der Aufbauphase. Werden Sicherheitsprobleme erst während der Laufzeit gesucht und behoben, treten sie wahrscheinlich immer wieder auf, weil die Fehler im zugrunde liegenden Image stecken.
Auch laut Red Hat ist es wichtig, die Container gemäß Industriestandards zu managen und automatisiert nach Schwachstellen zu untersuchen. Zudem sollten dabei Richtlinien berücksichtigt werden, die im Ernstfall automatisch Rebuilds der Container auslösen. Es ist in der Regel effizienter und sicherer, einen Container neu zu bauen, als ihn zu patchen.
In dieser Phase sollten IT-Teams sich an diesen drei Fragen orientieren: Gibt es Tools zur Komponentenanalyse, mit denen sich Probleme identifizieren lassen? Können Werkzeuge entwickelt werden, die eine automatische richtlinienbasierte Implementierung sicherstellen? Wie lässt sich das Patching ausgeführter Container vermeiden, so dass sie stattdessen per Trigger mit Hilfe automatischer Updates neu erstellt werden?
>> Infrastruktur <<
Auch die zugrunde liegende Infrastruktur einer Angriffsfläche gilt es abzusichern. Dabei sollte laut Red Hat die vom Host-Betriebssystem bereitgestellte Isolierung geprüft werden. Um Zugriffe über andere Container oder Breakouts zu verhindern, ist darauf zu achten, dass das System eine maximale Container-Trennung ermöglicht. Mit Namespaces können Administratoren mehrere virtuelle Instanzen der Ressourcen eines Hosts und eines Kernels definieren und getrennt nutzen. Hier schlägt Red Hat folgende Leitfragen vor: Welche Container müssen aufeinander zugreifen können? Wie können Container einander entdecken? Wie sollen Zugang und gemeinsame Ressourcen (beispielsweise Netz und Storage) kontrolliert werden? Wie werden Host-Updates verwaltet? Müssen alle Container gleichzeitig aktualisiert werden? Wie wird der Container-Status überwacht? Wie lässt sich die Anwendungskapazität bedarfsabhängig skalieren? Weitere Sicherheitstipps im Kubernetes-Umfeld gibt IT-Security-Expertin Chenxi Wang. Sie rät dazu, auf jeden Fall Linux-eigene Sicherheitsmechanismen wie SELinux und Seccomp Profiles zu nutzen. Darüber hinaus sollte die Knotenkommunikation mit einem TLS-Client-Zertifikat gesichert werden, um alle kritischen API-Zugangspunkte durchgängig mit TLS zu verschlüsseln. Allerdings darf hierbei nicht die oben erwähnte Anfälligkeit für einen Bleichenbacher-Angriff vergessen werden. Auch der direkte Zugang zu KubernetesKnoten, beispielsweise via Secure-Shell-(SSH-) Protokoll, sollte eingeschränkt werden. Sind Zugriffe auf Knoten nur über Kubernetes möglich, kann das IT-Team sie dort kontrollieren und loggen. So lassen sich unbefugte Zugriffe auf Host-Ressourcen verhindern.
>> Neue Prozesse und Governance <<
Sollen Container-basierte Microservices zum Einsatz kommen, müssen Betriebsprozesse um diese Services herum neu aufgebaut werden. Die etablierten Abläufe aus starren monolithischen Softwarestrukturen funktionieren dann nicht mehr. So wird beispielsweise klassisches Patch-Management von Maschinen durch Pipeline-Management abgelöst. Dazu gehören auch Sicherheitsaspekte wie Security-Assessments von heruntergeladenen Images, Zugriffsrechte oder offene Ports.
Steht der strategische Überbau, gilt es, an die Umsetzung heranzugehen. Dazu rät der Sicherheitsspezialist Thomas Schumacher von Accenture, eine passende Architektur zu wählen. Darauf aufbauend sollten die nötigen Richtlinien festgelegt werden, die das Sicherheitsniveau gewährleisten. Anschließend gilt es zu erarbeiten, wie diese Richtlinien eingehalten werden können. Dabei spielt es eine Rolle, wofür die jeweiligen Container-Anwendungen genutzt werden. In kritischen Teilen der Infrastruktur kann es beispielsweise ratsam sein, von einer Deny-all-Policy auszugehen und jede nötige Beziehung einzeln freizugeben.