Um Anwendungen besser skalierbar, schneller verfügbar oder leicht portierbar zu machen, setzen mittlerweile viele Unternehmen auf Containertechnologie. Deren kurze Lebensspanne und eingeschränkte Funktionalität bieten einige Sicherheitsvorteile, dennoch gibt es Risiken.
Ob dabei auf die Single-Host-basierte Bereitstellung mit Docker und Podman oder Orchestrierungs-Plattformen wie Kubernetes und OpenShift gesetzt wird, spielt keine Rolle. Jede Umgebung birgt gewisse Risiken, die den Betrieb von Containern unsicher gestalten können. Dazu gehören unter anderem:
- Die Verwendung von unsicheren Images
Viele Images verwenden Basis-Images aus öffentlichen Quellen wie Docker.hub. Werden diese Images nicht auf Schwachstellen gescanned, kann man sich auf diese Weise schnell Unsicherheiten ins Haus holen.
- Container laufen im privileged-mode
Container die „privileged“ sind, haben auch auf dem Host-System alle Berechtigungen, die der User besitzt und können damit erheblichen Schaden verursachen (mehr dazu in unserem Beitrag „Rootfull oder rootless?“ von Martin).
- Unbegrenzte Kommunikation zwischen Containern
Containern sollte die Kommunikation untereinander nur möglich sein, sofern diese notwendig ist, wie zum Beispiel zwischen Backend und Datenbank. Der Vorteil von Containern – die Isolierung einzelner Services (Microservice-Ansatz) – geht komplett verloren, wenn alle Container miteinander kommunizieren können.
- Im Container laufen schadhafte Prozesse
Schadhafte Prozesse könnten zum Beispiel reverse Shells beziehungsweise code injenctions zur Folge haben.
Bevor auf Tools eingegangen wird, die an verschiedenen Stellen in den QA-Prozess eingebunden werden können, muss erwähnt werden, dass Plattformen wie zum Beispiel OpenShift durch eigene Architektur, Policies und Features viele Risiken schon im Vorfeld minimieren. Openshift gestattet beispielsweise keinem Container, im privileged-mode zu starten. Da auf diesem Wege aber nicht alles abgedeckt werden kann, sollte in allen Schritten des Containerdeployments zusätzlich getestet werden. Die Sicherheit der laufenden Infrastruktur spielt selbstverständlich auch eine große Rolle, wird in diesem Artikel allerdings nicht behandelt, da dies in den meisten Fällen im Verantwortungsbereich des IT-Betriebs und nicht der Softwareentwicklung liegt.
Bei Betrachtung der einzelnen Schritte des Containerdeployments lassen sich drei Stufen erkennen, an denen angesetzt werden sollte, nämlich dem Code (Dockerfile, YAML‘s), dem Artifact (Image) und beim Deployment (Container).
Clean Code als Basis
Bevor auf Basis von Dockerfiles oder YAML‘s ein Build beziehungsweise ein Deployment gestartet wird, sollte sichergestellt werden, dass die Dateien den Konventionen und Best Practices folgen, welche empfohlen werden. Oft eingesetzte Tools für bessere Codequalität sind beispielsweise SonarQube (https://www.sonarqube.org) oder Veracode (https://www.veracode.com). Hiermit lassen sich auch hervorragend Fehler und Schwachstellen in Skripten oder im Code der Applikation finden. Damit diese Tools auch Dockerfiles oder YAML‘s auf Schwachstellen untersuchen können, müssen gegebenenfalls Linter integriert oder zusätzlich während der Entwicklung verwendet werden.
Bekannte Linter für das Prüfen von Dockerfiles sind:
- Hadolint
- Helmlint
Für das Prüfen von YAML‘s können z.B. folgende Linter verwendet werden:
- KubeLinter
- yamllint
Sichere Images
In Daniels Artikel „Der Weg zum eigenen Container-Image“ haben wir beschrieben, wie ein eigenes Image erstellt wird. Es kann natürlich vorkommen, dass aufgrund von wenigen Kapazitäten als auch fehlendem Know-how fertige Images aus öffentlichen Quellen verwendet werden. Da es hier keine Garantie dafür gibt, was sich alles innerhalb des Images verbirgt, sollte man entsprechend vorsichtig sein. Generell wird empfohlen, nur Images aus vertrauenswürdigen Quellen zu verwenden, wie z.B. quay.io oder Images von Dockerhub mit dem Tag „Official Image“.
Unabhängig davon, welche Images verwendet werden, müssen diese getestet werden. Hierfür bieten sich statische Analyse-Tools an. Diese prüfen Images auf Common Vulnerabilities and Exposures, kurz CVE.
Tools, die Sie hierfür verwenden können, sind:
- RedHat Clair
- Stackrox
- Trivy
- Grype
- Snyke
Containertests zur Laufzeit
Mit der statischen Analyse des Codes und des Images wird die bestmögliche Grundlage geschaffen, um Container sicher und zuverlässig zu starten und zu betreiben. Es ist dennoch sinnvoll und empfohlen, Container zur Laufzeit zu testen. Selbstverständlich können und sollten die gleichen Sicherheitsprüfungen durchgeführt werden, welche auch bei der Bereitstellung ohne Container genutzt werden. Es gibt allerdings auch potenzielle Risiken, welche Container-spezifisch sind.
Dazu gehören unter anderem:
- Ausbrechen aus dem Container (Änderung von Dateien auf Hostebene)
- Kommunikation zwischen Containern, die füreinander unsichtbar sein sollten
- Änderungen auf Dateiebene innerhalb des Containers, welche Prozesse verfälschen könnten
- Änderungen an einem Image durch Man-In-The-Middle-Angriffe
Ein passendes Analyse- und Testtool zum Aufspüren containerspezifischer Schwachstellen ist Red Hat Advanced Cluster Security for Kubernetes.
Mit der dynamischen Analyse des Containers – zusätzlich zur statischen Analyse des Codes und Images – wurden alle Möglichkeiten eingesetzt, um den Betrieb von Anwendungen in Containern sicher zu gestalten. Diese Analysen können als Ergänzung zu weiteren funktionalen und nicht-funktionalen Tests betrachtet werden, die in einer Pipeline zur umfassenden Qualitätssicherung integriert sein sollten, ebenso wie die Durchführung von manuellen Penetration-Tests.
Bei der Integration oben genannter Tools in eure eigene Pipeline unterstützen wir gern.