chroot und Jails: Grundlagen der Prozessisolation
AI generated
$
/etc
Linux · chroot · Prozessisolation
chroot und Jails: Grundlagen der Isolation
Root-Verzeichnis wechseln, ohne sich zu täuschen

chroot ist eines der ältesten Isolationswerkzeuge unter Unix und gleichzeitig eines der am meisten missverstandenen. Wer eine Jail-Umgebung aufbaut, um einen Prozess vom Rest des Dateisystems abzuschotten, muss genau verstehen, was chroot tatsächlich absichert und wo diese Absicherung endet, denn viele Server wurden schon über eine als sicher geglaubte chroot-Umgebung kompromittiert.

14 Min. Lesezeit chroot · Jail · Prozessisolation · Namespaces Linux · Debian · Ubuntu · RHEL

1. Was Prozessisolation bedeutet und warum chroot existiert

Prozessisolation bezeichnet die Idee, einem laufenden Prozess absichtlich nur einen begrenzten Ausschnitt der Systemressourcen sichtbar zu machen, statt ihm den vollen Zugriff auf das gesamte System zu erlauben. chroot, kurz für change root, ist der historisch erste und einfachste Baustein dieser Idee unter Unix: Der Systemaufruf ändert für einen Prozess und alle seine Kindprozesse das Wurzelverzeichnis, sodass dieser Prozess ein bestimmtes Unterverzeichnis fortan als / wahrnimmt und alles außerhalb davon schlicht nicht mehr sieht.

Die ursprüngliche Motivation für chroot war weniger Sicherheit als Testbarkeit: Entwickler wollten in den 1970er Jahren neue Softwareversionen in einer isolierten Verzeichnisstruktur testen, ohne das produktive System zu gefährden. Erst später etablierte sich die Vorstellung, chroot ließe sich auch als Sicherheitsgrenze gegen kompromittierte Dienste einsetzen, ein Missverständnis, das bis heute zu unsicheren Konfigurationen führt. Wer eine Jail, also eine mit chroot abgeschottete Umgebung, aufsetzt, sollte deshalb zuerst verstehen, wofür das Werkzeug tatsächlich entworfen wurde.

2. chroot-Grundlagen: das Root-Verzeichnis ändern

Der Befehl chroot /pfad/zur/jail /bin/bash startet eine neue Bash-Instanz, deren Wurzelverzeichnis auf /pfad/zur/jail gesetzt ist. Innerhalb dieser Shell verweist /etc/passwd nicht mehr auf die systemweite Datei, sondern auf /pfad/zur/jail/etc/passwd, sofern diese überhaupt existiert. Genau hier liegt die erste praktische Hürde: chroot ändert nur die Sicht auf das Dateisystem, es kopiert keine Dateien und richtet keine Umgebung ein. Fehlt eine benötigte Datei innerhalb der Jail, meldet der Prozess schlicht, dass sie nicht existiert, obwohl sie außerhalb der Jail durchaus vorhanden wäre.

Wichtig ist außerdem, dass chroot ausschließlich Root-Rechte voraussetzt, denn ohne diese Einschränkung könnte jeder Benutzer beliebige Pfadwechsel vornehmen und damit die Sicherheitsannahmen des Systems unterlaufen. Der Kernel selbst erzwingt diese Beschränkung über die Capability CAP_SYS_CHROOT. Nach dem Wechsel bleibt der Prozess dauerhaft in der neuen Root-Sicht gefangen, es sei denn, er verfügt weiterhin über Root-Rechte und nutzt einen bekannten Fluchtweg, der im Abschnitt zu den Grenzen von chroot beschrieben wird.


# Create a minimal jail directory structure
mkdir -p /srv/jail/{bin,lib,lib64,usr,etc,dev,proc}

# Change root and start a shell inside — requires root privileges
sudo chroot /srv/jail /bin/bash
# Inside the chroot, / now refers to /srv/jail on the host
ls /            # shows only what exists under /srv/jail
cat /etc/passwd # fails unless /srv/jail/etc/passwd was created
exit            # returns to the original shell, outside the jail

3. Eine chroot-Jail Schritt für Schritt aufbauen

Der Aufbau einer funktionierenden Jail beginnt mit der Verzeichnisstruktur, die ein Programm für seinen normalen Betrieb erwartet: mindestens /bin, /lib, häufig /lib64 auf 64-Bit-Systemen, sowie /etc für Konfigurationsdateien, die das Programm tatsächlich benötigt. Anschließend kopiert man die gewünschten Binaries, etwa bash oder ls, in das entsprechende Verzeichnis der Jail. Der entscheidende Schritt danach ist häufig der am meisten übersehene: Jedes kopierte Binary bringt eigene Abhängigkeiten an dynamischen Bibliotheken mit, die ebenfalls innerhalb der Jail bereitgestellt werden müssen, sonst schlägt der Start mit einem Fehler wie "No such file or directory" fehl, obwohl die Datei sichtbar vorhanden ist.

Das Werkzeug ldd listet genau diese Abhängigkeiten auf und ist damit der zentrale Helfer beim Jail-Aufbau. Für jede Zeile aus der ldd-Ausgabe muss die entsprechende Bibliothek an derselben relativen Pfadposition innerhalb der Jail existieren, wie sie außerhalb referenziert wird. Bei komplexeren Programmen mit vielen Abhängigkeiten summiert sich dieser Aufwand schnell, weshalb produktive Jails heute meist mit fertigen Werkzeugen wie debootstrap aufgebaut werden, die automatisch ein minimales, konsistentes Basissystem in ein Zielverzeichnis installieren.


#!/usr/bin/env bash
# Populate a chroot jail with a binary and its shared library dependencies
set -euo pipefail

JAIL="/srv/jail"
BINARY="/bin/ls"

# Copy the binary itself into the jail, preserving its relative path
mkdir -p "$JAIL$(dirname "$BINARY")"
cp "$BINARY" "$JAIL$BINARY"

# Resolve dynamic library dependencies and copy each one
ldd "$BINARY" | awk '{print $3}' | grep '^/' | while read -r lib; do
  mkdir -p "$JAIL$(dirname "$lib")"
  cp -n "$lib" "$JAIL$lib"
done

# The dynamic linker itself must also be present
LINKER=$(ldd "$BINARY" | grep -o '/lib.*ld-linux[^ ]*')
mkdir -p "$JAIL$(dirname "$LINKER")"
cp -n "$LINKER" "$JAIL$LINKER"

4. Binaries, Bibliotheken und Devices in der Jail

Über Binaries und Bibliotheken hinaus benötigen viele Programme Zugriff auf virtuelle Dateisysteme wie /proc und Gerätedateien wie /dev/null oder /dev/urandom. Diese existieren nicht automatisch innerhalb der Jail, sondern müssen explizit über mount --bind beziehungsweise als eigenständige Gerätedateien mit mknod eingebunden werden. Fehlt etwa /dev/null, scheitern viele Standard-Tools bereits beim Versuch, Ausgaben dorthin umzuleiten, mit einer schwer nachvollziehbaren Fehlermeldung.

Der Bind-Mount ist dabei die deutlich robustere Wahl gegenüber manuell mit mknod erzeugten Gerätedateien, weil er die Berechtigungen und Eigenschaften der Originaldatei automatisch übernimmt und bei Änderungen am Host synchron bleibt. Ein häufiges Muster in produktiven Jails ist deshalb, /dev, /proc und teilweise /sys vom Host per Bind-Mount in die Jail einzuhängen, statt eigene, isolierte Kopien dieser virtuellen Dateisysteme zu pflegen.


# Bind-mount host device and proc filesystems into the jail
sudo mount --bind /dev /srv/jail/dev
sudo mount --bind /dev/pts /srv/jail/dev/pts
sudo mount -t proc proc /srv/jail/proc

# Verify from inside the jail
sudo chroot /srv/jail /bin/bash -c 'ls /dev; cat /proc/version'

# Always unmount in reverse order before deleting the jail directory
sudo umount /srv/jail/proc
sudo umount /srv/jail/dev/pts
sudo umount /srv/jail/dev

5. Die Grenzen von chroot: kein Sicherheitsfeature im eigentlichen Sinn

Der wichtigste Punkt zu chroot ist, dass es niemals als alleinige Sicherheitsgrenze gedacht war und heute in der Sicherheitsliteratur ausdrücklich nicht als solche empfohlen wird. Ein Prozess mit Root-Rechten innerhalb einer chroot-Jail kann diese unter bestimmten Bedingungen verlassen, klassischerweise über den sogenannten "chroot breakout" mittels eines zweiten chroot()-Aufrufs kombiniert mit einem offenen Dateideskriptor außerhalb der Jail, der noch aus der Zeit vor dem Wechsel stammt. Dieser Fluchtweg ist seit Jahrzehnten dokumentiert und funktioniert bis heute, wenn der Prozess innerhalb der Jail Root-Rechte besitzt.

Zusätzlich isoliert chroot weder Prozess-IDs noch Netzwerk-Sockets noch Benutzer-IDs. Ein Prozess innerhalb der Jail sieht weiterhin dieselben Prozesse über /proc, sofern dieses eingebunden ist, kann weiterhin auf offene Netzwerkports des Hosts zugreifen und teilt sich denselben Kernel vollständig mit dem restlichen System. Für echte Sicherheitsisolation braucht es zusätzlich Linux-Namespaces, cgroups und idealerweise den Verzicht auf Root-Rechte innerhalb der Jail, also genau die Bausteine, aus denen moderne Container-Laufzeiten aufgebaut sind.

6. Praxisbeispiel: chroot für SFTP und Rescue-Systeme

Ein legitimer und bis heute weit verbreiteter Einsatzzweck von chroot ist die Beschränkung von SFTP-Benutzern auf ihr eigenes Verzeichnis über ChrootDirectory in der OpenSSH-Konfiguration. Da diese Benutzer keine Root-Rechte innerhalb der Jail besitzen und OpenSSH selbst die Jail-Umgebung streng kontrolliert, entfällt hier das Problem des chroot-Breakouts weitgehend, solange keine setuid-Binaries in der Jail bereitgestellt werden. Diese Konfiguration ist deutlich robuster als ein allgemeiner chroot-Aufruf für beliebige Dienste.

Ein zweiter klassischer Anwendungsfall ist das Rescue-System eines Servers: Bootet man von einem Live-System, um ein defektes Betriebssystem zu reparieren, chrootet man in die eigentliche Systempartition, um Werkzeuge wie grub-install oder dpkg mit dem korrekten Root-Kontext auszuführen, statt sie auf das Live-System selbst anzuwenden. In diesem Szenario ist chroot kein Sicherheitswerkzeug, sondern ein reines Kontextwechsel-Werkzeug, das genau seiner ursprünglichen Bestimmung entspricht.


# /etc/ssh/sshd_config — restrict a user to their home directory via chroot
Match User sftpuser
  ChrootDirectory /srv/sftp/%u
  ForceCommand internal-sftp
  AllowTcpForwarding no
  X11Forwarding no

7. Häufige Fallstricke beim Betrieb einer Jail

Der häufigste Fehler ist, eine Jail einzurichten und dabei zu vergessen, dass Zeitzonendaten, DNS-Auflösung über /etc/resolv.conf und Locale-Dateien ebenfalls innerhalb der Jail vorhanden sein müssen, wenn der eingesperrte Prozess Netzwerkzugriffe durchführt oder lokalisierte Ausgaben erzeugt. Ohne diese Dateien scheitern DNS-Auflösungen scheinbar grundlos, obwohl das Netzwerk selbst funktioniert, weil der Prozess innerhalb der Jail schlicht keine gültige resolv.conf findet.

Ein zweiter verbreiteter Fehler ist, vergessene Bind-Mounts beim Löschen einer Jail-Verzeichnisstruktur zu übersehen. Löscht man das Jail-Verzeichnis mit rm -rf, während /dev oder /proc noch eingehängt sind, werden versehentlich Inhalte des Host-Dateisystems gelöscht, weil rm -rf transparent durch den Bind-Mount hindurch operiert. Vor jeder Löschung einer Jail müssen deshalb alle Bind-Mounts zuverlässig mit umount in umgekehrter Reihenfolge entfernt werden.

8. chroot vs. Namespaces vs. Container: die Abgrenzung

Moderne Container-Laufzeiten wie Docker nutzen chroot beziehungsweise dessen sichereren Nachfolger pivot_root lediglich als eine von mehreren Isolationsschichten. Zusätzlich kommen Linux-Namespaces zum Einsatz, die Prozess-IDs, Netzwerk-Stacks, Hostnamen und Benutzer-IDs jeweils eigenständig isolieren, sowie cgroups, die Ressourcenlimits für CPU und Speicher durchsetzen. Ein Container ist also technisch eine Kombination aus chroot-artiger Dateisystemisolation plus Namespaces plus cgroups, nicht ein Ersatz für chroot, sondern eine erhebliche Erweiterung.

Wer heute eine echte Sicherheitsgrenze benötigt, sollte deshalb direkt zu Namespaces und containerbasierten Werkzeugen greifen, statt chroot allein als vermeintliche Isolationsschicht zu betrachten. chroot bleibt dennoch relevant als leichtgewichtiges Werkzeug für Fälle, in denen keine echte Sicherheitsgrenze gebraucht wird, sondern lediglich eine kontrollierte Dateisystemsicht, etwa bei SFTP-Jails oder Build-Umgebungen für Paketierung.

9. Debugging und Vergleichstabelle

Zum Debugging einer nicht startenden Jail-Umgebung liefert strace -f chroot /srv/jail /bin/programm die genaue Stelle, an der ein fehlendes File oder eine fehlende Bibliothek den Start verhindert. ldd innerhalb der Jail selbst zeigt, ob alle Abhängigkeiten eines Binaries tatsächlich aufgelöst werden können. Für die laufende Jail hilft lsof auf dem Host, um offene Dateideskriptoren des chrooteten Prozesses zu identifizieren, die potenziell einen Fluchtweg darstellen könnten.

Mechanismus Isoliert Dateisystem Isoliert Prozesse/Netzwerk Sicherheitsgrenze
chroot Ja Nein Schwach, umgehbar mit Root
chroot + Non-Root Ja Nein Für einfache Fälle ausreichend (SFTP)
Linux Namespaces Ja (mit pivot_root) Ja Deutlich stärker
Docker-Container Ja Ja Namespaces + cgroups + Seccomp

Diese Tabelle zeigt deutlich, dass chroot allein am unteren Ende der Isolationsskala steht. Für produktive Sicherheitsanforderungen ist immer mindestens die Kombination mit Namespaces und dem Verzicht auf Root-Rechte innerhalb der Jail notwendig.

Mironsoft

Linux-Serverhärtung und Prozessisolation für PHP-Hosting

Isolation, die tatsächlich hält, was sie verspricht?

Wir bewerten bestehende chroot-Jails auf ihre tatsächliche Sicherheitswirkung, migrieren kritische Dienste auf Namespaces und Container, und richten SFTP- oder Build-Jails sauber und wartbar ein.

Isolations-Audit

Prüfung bestehender Jails auf Breakout-Risiken und fehlende Non-Root-Konfiguration

SFTP-Jails

Saubere ChrootDirectory-Konfiguration für Kunden- und Deployment-Zugänge

Container-Migration

Umzug kritischer Dienste von chroot auf Namespaces und cgroups

10. Zusammenfassung

chroot ändert die Sicht eines Prozesses auf das Wurzelverzeichnis und war ursprünglich für Testumgebungen gedacht, nicht für Sicherheitsisolation. Eine funktionierende Jail braucht eigene Kopien aller benötigten Binaries, deren Bibliotheksabhängigkeiten sowie Bind-Mounts für /dev und /proc. Ein Prozess mit Root-Rechten kann eine chroot-Jail über bekannte Techniken verlassen, weshalb chroot niemals als alleinige Sicherheitsgrenze dienen sollte.

Sinnvolle Einsatzzwecke bleiben SFTP-Beschränkungen ohne Root-Rechte, Rescue-Systeme und Build-Umgebungen. Für echte Sicherheitsisolation braucht es zusätzlich Linux-Namespaces und cgroups, also genau die Bausteine, aus denen moderne Container bestehen. Wer diese Abgrenzung kennt, nutzt chroot dort, wo es sinnvoll ist, und verlässt sich für kritische Isolationsanforderungen auf die stärkeren, moderneren Werkzeuge.

chroot und Jails: Das Wichtigste auf einen Blick

Funktionsweise

Ändert nur das Wurzelverzeichnis eines Prozesses, kopiert oder installiert keine Dateien automatisch.

Jail-Aufbau

Binaries, ldd-Abhängigkeiten und Bind-Mounts für /dev und /proc sind notwendig, sonst schlägt der Start fehl.

Grenzen

Kein Schutz gegen Root-Prozesse, keine Isolation von Prozess-IDs, Netzwerk oder Benutzer-IDs.

Empfehlung

Für echte Sicherheit zusätzlich Namespaces und cgroups einsetzen, chroot nur für Non-Root-Fälle wie SFTP.

11. FAQ: chroot und Jails

1Ist chroot ein Sicherheitsfeature?
Nein, ursprünglich für Testumgebungen gedacht. Root-Prozesse können die Jail verlassen.
2Warum fehlen kopierte Dateien?
chroot ändert nur die Dateisystemsicht, kopiert nichts automatisch. Jede Datei muss manuell platziert werden.
3Benötigte Bibliotheken finden?
ldd zeigt alle Bibliotheksabhängigkeiten samt Pfaden, die dann innerhalb der Jail bereitgestellt werden müssen.
4Was ist ein chroot-Breakout?
Eine bekannte Fluchttechnik über einen zweiten chroot-Aufruf mit einem offenen Dateideskriptor außerhalb der Jail.
5DNS funktioniert nicht in der Jail?
Wahrscheinlich fehlt /etc/resolv.conf innerhalb der Jail, muss manuell kopiert oder eingebunden werden.
6Ist SFTP-Jail sicher?
Deutlich sicherer, weil OpenSSH die Jail streng kontrolliert und keine Root-Rechte darin bestehen.
7chroot vs. Namespaces?
chroot isoliert nur das Dateisystem, Namespaces zusätzlich Prozesse, Netzwerk und Benutzer-IDs.
8Jail einfach mit rm -rf löschen?
Nur nach umount aller Bind-Mounts, sonst werden Host-Dateien versehentlich gelöscht.
9chroot beim Systemrescue?
Wechselt den Root-Kontext zur Systempartition, damit Reparatur-Tools korrekt arbeiten.
10Noch für neue Projekte sinnvoll?
Für echte Isolation in Kombination mit Namespaces, für einfache Non-Root-Fälle allein weiterhin brauchbar.