# Docker-Container sind unsicher > Container bieten Isolation — wenn du sie auf einem vollständig gepatchten Host betreibst, sollte es also gar keine Sicherheitslücken geben. Weit gefehlt. - URL: https://blog.goroot.de/de/post/docker-containers-are-insecure/ - Erstveröffentlichung: 2018-01-14 - Lastmod: 2018-01-14 - 1162 Wörter, 6 min - Tags: debian, docker, icinga, linux, monitoring, patches, security - Autor: Michael Kolb — goroot (https://blog.goroot.de/de/) --- Jeder weiß, wie man eine Linux-Box aktuell hält. Es gilt auch als gesunder Menschenverstand, dass das Ausführen von Dingen in Docker-Containern per Definition sicherer ist. Schließlich isolieren sie Dienste voneinander. Wenn du also Container auf einem vollständig gepatchten Host betreibst, sollte es gar keine Sicherheitslücken geben. Weit gefehlt! Container aktuell zu halten ist eine ganz andere Geschichte. Das wirft die Fragen auf, wie man seine Container aktuell hält und wie man entscheidet, ob sich Containerisierung in deinem Szenario überhaupt lohnt. ## Was ist ein sicheres System? Die Definition eines sicheren Systems mag je nach Person unterschiedlich ausfallen. Ein System sicher zu halten ist natürlich viel mehr als nur die neuesten Patches und Updates einzuspielen, aber dennoch: Für ein durchschnittliches System ist das Installieren von Updates und Sicherheitspatches _der wichtigste_ Punkt, wenn Systeme dem Internet ausgesetzt sind. Aus Update-Perspektive muss es eine Art "Vertrauenskette" geben, um sein System sicher aktualisieren zu können. Bricht ein einzelnes Kettenglied, können deine Systeme kompromittiert werden, ohne dass du es überhaupt bemerkst: Lass uns diese Vertrauenskette definieren: * **Zeitnah aktualisieren** — Updates so bald wie möglich einspielen * **Sichere Quellen** — Alle Updates müssen aus vertrauenswürdigen Quellen bezogen werden. Die Voraussetzungen für eine vertrauenswürdige Quelle sind: * **Vertrauenswürdige Repositories** — Die Quellen / Server / Update-Seiten, von denen du deine Updates beziehst, müssen vertrauenswürdig sein * **Vertrauenswürdige Beiträge** — Gleiches gilt für die Inhalte dieser Repositories (bzw. den Quellcode, der die Grundlage für die Pakete bildet) * **Integrität sicherstellen** — Der Nachweis der Integrität eines Pakets (z. B. durch Signaturen) stellt sicher, dass sich der Paketinhalt auf dem Weg vom Autor zu deinem System nicht verändert hat Prüfen wir also, ob all diese Anforderungen beim Betrieb von Docker-Containern erfüllt sind. ## Der klassische Server Du betreibst Linux auf einer Bare-Metal-Box (oder einer virtuellen Maschine). Um sie aktuell zu halten, führst du von Zeit zu Zeit ein paar Befehle wie ```bash apt-get update apt-get upgrade ``` aus. Der Paketmanager deiner Distribution kümmert sich dann um den Update-Prozess. Er greift auf die Paket-Repositories zu, lädt die neuesten Sicherheitsupdates herunter und installiert sie schließlich auf deinem System. Aber warum müssen wir diese Updates eigentlich manuell durchführen? Können wir das nicht einfach automatisch erledigen lassen? Nun, zumindest bei klassischen Serversystemen kann ein automatisches Update dein System jederzeit lahmlegen. Datenbank-Upgrades, überschriebene individuelle Konfigurationen oder einfach unbeaufsichtigte Upgrades, die zu einem ungünstigen Zeitpunkt laufen, bereiten dir Kopfschmerzen. ### Ping mich an! Fortgeschrittenere Setups überwachen irgendwie den aktuellen Zustand des Systems und benachrichtigen den Administrator, dass ausstehende Updates vorliegen. Das kann entweder mit Tools wie [apticron](https://wiki.ubuntuusers.de/apticron/) geschehen, das dich per Mail benachrichtigt, sobald neue Updates verfügbar sind. Noch professionellere Setups nutzen ein dediziertes Monitoring-System wie [icinga2](https://www.icinga.com), um Alarme auszulösen. ### Ist unsere Kette gebrochen? Nein, eigentlich nicht. Wenn du deine Updates regelmäßig ausführst, kümmert sich dein Paketmanager um all die Anforderungen, die wir definiert haben: * **Zeitnah aktualisieren** — Erledigt! Wir werden benachrichtigt, sobald etwas zu installieren ist, und führen das Update sofort aus * **Sichere Quellen** — Erledigt! Alle unten definierten Anforderungen sind erfüllt * **Vertrauenswürdige Repositories** — Erledigt! Die Standard-Repositories deiner Distribution werden von denselben Leuten gepflegt, die auch deine Distribution gebaut haben. Wenn du denen nicht vertraust, hättest du die Distribution gar nicht erst genutzt. * **Vertrauenswürdige Beiträge** — Erledigt! Code-Änderungen werden von der Open-Source-Community überprüft, das Paketieren der finalen Artefakte übernimmt ein Paketmanager, der für den Paketinhalt verantwortlich ist. Zumindest bei Debian gibt es zusätzlich eine sehr lange Testphase, bevor Dinge in Produktion gehen. * **Integrität sicherstellen** — Erledigt! Dein Paketmanager prüft Signaturen und Prüfsummen der zu installierenden Pakete und warnt dich, falls etwas nicht stimmt ## Ab damit in einen Container Da wir also gehört haben, dass ein containerisierter Dienst sicherer ist, werfen wir alle unsere Dienste in ihre eigenen Container. Wir haben immer noch unsere Bare-Metal-Box mit Linux und einem Docker-Daemon, aber alles andere versteckt sich in mehreren Containern. Um unser Host-System aktuell zu halten, nutzen wir genau dieselbe Strategie, die wir im letzten Kapitel besprochen haben. Da unser Host-System aber aus nicht viel mehr als einem auf einem Kernel laufenden dockerd besteht, gibt es dort auch gar nicht so viele Updates. ### Frischer Anstrich für deine Container Wie aktualisiert man einen Container? Man aktualisiert das Docker-Image und startet die Maschine mit der neuen Image-Version neu. Ist das also nur ein weiterer Zweizeiler? ```bash docker pull imagename docker restart myContainer ``` Auf den ersten Blick: ja. Aber konzentrieren wir uns zunächst darauf, wie man alle seine Container aktuell hält. Vielleicht hast du eine ganze Menge davon laufen — willst du die wirklich alle einzeln von Hand aktualisieren? Es gibt mehrere Lösungen, um alle Container auf einmal zu aktualisieren. Eine davon ist [Watchtower](https://github.com/v2tec/watchtower). Es betreibt einen zusätzlichen Container, der alle anderen Container inspiziert und deine aktuellen Image-Versionen mit den neuesten Versionen in der Registry vergleicht. Wird ein neueres Image erkannt, lädt es dieses herunter, reißt deinen Container ab und startet ihn mit der neuesten Image-Version neu. Das alles geschieht ganz ohne manuelles Eingreifen. ### Dem Wal vertrauen? Prüfen wir noch einmal unsere Anforderungen für das Container-Szenario. Unsere Vertrauenskette ist nicht gebrochen, aber angerostet: Die Quellen unserer Images sind nicht so sicher wie die Paket-Repositories deiner Distribution. Die Bauanleitungen für die Images (auch bekannt als Dockerfiles) sind oft auf GitHub oder anderswo öffentlich verfügbar, aber es gibt auch viele Images, die nicht einmal ihre Dockerfiles veröffentlichen. Zusammengefasst: * Wenn das Dockerfile nicht verfügbar ist, nutzt du eine Blackbox ohne einfache Möglichkeit zur Einsicht, was eigentlich vor sich geht. Du kannst dir zwar immer die Historie deines Docker-Images ansehen, um eine Vorstellung davon zu bekommen. Aber ist das wirklich der richtige Weg für jedes einzelne Image-Update? * Wenn das Dockerfile verfügbar ist, hängt es davon ab, ob du überprüfen kannst, dass das veröffentlichte Dockerfile wirklich die Bauanleitung für das von dir verwendete Image ist. Bei Docker Hub wird das implizit durch deren Build-Prozess sichergestellt. Andernfalls gibt es keinen kryptographisch sicheren Weg (wie Signaturen), das wirklich zu belegen. Noch problematischer aus Sicherheitssicht ist der Inhalt des Images. Mit Docker ist der Prozess der Container-Aktualisierung noch stärker automatisiert (was auch ein Vorteil ist). Das bedeutet aber auch, dass in bestimmten Szenarien der Autor des Dockerfiles ganz allein entscheidet, welche Änderungen in Produktion gehen. Besonders bei kleineren Projekten gibt es überhaupt keine Code-Reviews. ## Fazit Die Frage, ob man einem Open-Source-Projekt vertrauen soll oder nicht, ist so alt wie Open Source selbst. Das Containerisieren deiner Dienste fügt lediglich eine weitere (potenziell) unsichere Schicht zu denen hinzu, die du in einem klassischen Szenario mit Daemons bereits hast. Immerhin gewinnst du definitiv an Sicherheit, da im Fehlerfall alles auf den bösartigen Container isoliert bleibt. Andererseits erhöht sich auch die Wahrscheinlichkeit, sich etwas Bösartiges einzufangen — besonders bei kleineren Projekten, die vielleicht nicht einmal Open Source sind. Welcher Weg der richtige ist, hängt immer von deinem Wissen über die verwendete Technologie und deiner Bereitschaft ab, Zeit in Sicherheit zu investieren. Sei dir einfach bewusst, dass du mehr Dinge berücksichtigen musst, als wenn du die Repositories deiner Distribution nutzt. Docker-Container sind also unsicher — aber nicht mehr als deine klassischen Systeme, wenn du es richtig machst ;-)