Linux Boot-Chain-Sicherheit und systemd Service-Härtung: Praxisleitfaden 2026

Praxisleitfaden zur Absicherung der Linux-Boot-Chain mit UEFI Secure Boot, TPM 2.0 und UKIs sowie zur systematischen Härtung von systemd-Services. Mit Konfigurationsbeispielen, Audit-Skripten und CI/CD-Integration.

Einleitung: Warum Boot-Chain-Sicherheit und Service-Härtung 2026 unverzichtbar sind

Mal ehrlich — wenn man sich die Zahlen anschaut, wird einem schon etwas mulmig. 2025 wurden 5.530 Kernel-CVEs veröffentlicht, das sind 28 Prozent mehr als im Vorjahr. Ransomware-Gruppen wie BlackCat und LockBit werden immer raffinierter und setzen gezielt auf Kernel-Exploits, um Sicherheitsmechanismen direkt auf Betriebssystemebene auszuhebeln. Und wenn der Bootprozess einmal kompromittiert ist? Dann sind alle darüber liegenden Schutzschichten — von SELinux bis zur Application-Level-Firewall — praktisch wirkungslos.

Dazu kommt ein ziemlich konkretes Problem: Im Dezember 2025 hat die NSA eine aktualisierte Richtlinie zur UEFI-Secure-Boot-Konfiguration herausgegeben. Die klare Empfehlung: benutzerdefinierte Schlüssel statt der vorinstallierten Herstellerschlüssel verwenden. Der Hintergrund ist ernst — am 26. Juni 2026 läuft das Microsoft UEFI CA-Zertifikat von 2011 aus. Ja, genau das Zertifikat, das praktisch alle Linux-Distributionen zum Signieren ihrer Bootloader nutzen. Wer hier nicht rechtzeitig reagiert, riskiert, dass Systeme nach einem Firmware-Update schlicht nicht mehr hochfahren.

Gleichzeitig hat sich systemd als Standard-Init-System auf so gut wie allen Enterprise-Linux-Distributionen durchgesetzt. Die Sicherheitsdirektiven, die systemd mitbringt, sind beeindruckend — werden aber erschreckend selten genutzt. Über 70 Prozent aller produktiven systemd-Service-Units haben nicht eine einzige Härtungsmaßnahme konfiguriert. Das ist im Grunde eine offene Einladung für jeden Angreifer, der bereits einen Fuß in der Tür hat.

In diesem Leitfaden gehen wir die komplette Sicherheitskette durch: vom allerersten Firmware-Befehl beim Einschalten bis zur gehärteten Ausführung einzelner Dienste im laufenden Betrieb. Keine reine Theorie — Sie bekommen praxiserprobte Befehle und Konfigurationen, die Sie direkt einsetzen können.

UEFI Secure Boot verstehen

Was ist UEFI Secure Boot?

UEFI Secure Boot ist ein Sicherheitsmechanismus in der UEFI-Firmware, der dafür sorgt, dass beim Bootvorgang nur Software ausgeführt wird, die mit einem vertrauenswürdigen kryptografischen Schlüssel signiert wurde. Klingt simpel, ist aber enorm wirkungsvoll: Es verhindert, dass Bootkits, Rootkits oder manipulierte Bootloader den Startprozess kapern, bevor das Betriebssystem überhaupt geladen ist.

Die Boot-Chain im Detail

So sieht der gesicherte Bootprozess auf einem typischen Linux-System aus:

  1. UEFI-Firmware: Die Firmware initialisiert die Hardware und prüft die Signatur des ersten Bootloaders. Nur bei erfolgreicher Validierung gegen die gespeicherten Schlüssel geht's weiter.
  2. Shim: Ein kleiner, von Microsoft signierter Bootloader, der zwischen UEFI-Firmware und dem eigentlichen Bootloader vermittelt. Shim enthält den öffentlichen Schlüssel der jeweiligen Linux-Distribution und kann zusätzliche Machine Owner Keys (MOK) laden.
  3. GRUB2: Der eigentliche Bootloader, verifiziert durch Shim. GRUB2 lädt die Kernel-Konfiguration, zeigt das Boot-Menü und übergibt dann die Kontrolle an den Linux-Kernel.
  4. Linux-Kernel: Wird von GRUB2 verifiziert und geladen. Ab hier übernimmt der Kernel — und kann über Mechanismen wie das IMA-Subsystem (Integrity Measurement Architecture) die Integrität weiterer Dateien sicherstellen.

Die Schlüsselhierarchie: PK, KEK, DB und DBX

Das Sicherheitsmodell basiert auf einer hierarchischen Schlüsselstruktur. Wer hier den Überblick hat, versteht Secure Boot wirklich:

  • Platform Key (PK): Der Wurzelschlüssel der gesamten Vertrauenskette. Wird typischerweise vom Hardwarehersteller gesetzt. Auf selbst verwalteten Systemen sollten Sie unbedingt Ihren eigenen PK einrollen.
  • Key Exchange Key (KEK): Autorisiert Änderungen an den Signaturdatenbanken DB und DBX. Sowohl Microsoft als auch der Hardwarehersteller können KEKs hinterlegen.
  • Signature Database (DB): Enthält die vertrauenswürdigen Zertifikate und Hashes, gegen die Boot-Software verifiziert wird — typischerweise das Microsoft-Zertifikat und die Zertifikate der Linux-Distributionen.
  • Forbidden Signature Database (DBX): Die Widerrufsliste. Hier landen Hashes oder Zertifikate, denen nicht mehr vertraut werden soll, etwa nach einer Schwachstelle in einem Bootloader.
Wichtig: Wer den PK kontrolliert, kontrolliert die gesamte Vertrauenskette. In Enterprise-Umgebungen sollten Sie ernsthaft darüber nachdenken, den herstellerseitigen PK durch einen eigenen zu ersetzen und eine vollständig selbst verwaltete Schlüsselhierarchie aufzubauen.

Secure Boot auf Linux konfigurieren

Aktuellen Status überprüfen

Bevor Sie irgendetwas an der Secure-Boot-Konfiguration ändern, schauen Sie sich erstmal den aktuellen Zustand an:

# Secure Boot Status prüfen
mokutil --sb-state

# Erwartete Ausgabe bei aktiviertem Secure Boot:
# SecureBoot enabled

# Alle eingerollten Schlüssel anzeigen
mokutil --list-enrolled

# UEFI-Variablen direkt abfragen
efi-readvar

Falls mokutil --sb-state die Ausgabe SecureBoot disabled liefert, müssen Sie Secure Boot zunächst im UEFI-Setup aktivieren. Aber Vorsicht: Bei laufenden Systemen braucht das sorgfältige Planung, denn nicht signierte Kernel und Module werden danach nicht mehr geladen.

Eigene Schlüssel mit sbctl erstellen und verwalten

Das Tool sbctl macht die Verwaltung eigener Secure-Boot-Schlüssel deutlich angenehmer. Es wurde speziell für Linux entwickelt und automatisiert viele der sonst recht mühsamen manuellen Schritte:

# sbctl installieren (Arch Linux)
pacman -S sbctl

# sbctl installieren (Ubuntu/Debian - aus den Quellen)
apt install golang-go
go install github.com/foxboron/sbctl/cmd/sbctl@latest

# Status prüfen
sbctl status

# Neue Schlüssel generieren (PK, KEK, DB)
sbctl create-keys

# Die Schlüssel werden standardmäßig unter /usr/share/secureboot/ abgelegt
ls -la /usr/share/secureboot/keys/

# Schlüssel in die Firmware einrollen
# ACHTUNG: Dies erfordert, dass Secure Boot im Setup Mode ist
sbctl enroll-keys

# Mit Microsoft-Schlüsseln kombiniert einrollen (empfohlen für Dual-Boot)
sbctl enroll-keys --microsoft

Kernel und Bootloader signieren

Sobald die eigenen Schlüssel stehen, müssen alle relevanten Boot-Komponenten signiert werden:

# Alle zu signierenden Dateien anzeigen
sbctl verify

# Kernel signieren
sbctl sign -s /boot/vmlinuz-linux
sbctl sign -s /boot/vmlinuz-linux-lts

# GRUB-Bootloader signieren
sbctl sign -s /boot/EFI/BOOT/BOOTX64.EFI
sbctl sign -s /boot/EFI/systemd/systemd-bootx64.efi

# Initramfs muss nicht signiert werden, wenn es in den
# Unified Kernel Image eingebettet wird (siehe Abschnitt UKI)

# Alle registrierten Dateien anzeigen
sbctl list-files

# sbctl kann beim Kernel-Update automatisch neu signieren
# durch den pacman-Hook (Arch) oder den kernel-install-Hook

Machine Owner Keys (MOK) einrollen

Der MOK-Mechanismus ist besonders praktisch, wenn Sie den herstellerseitigen PK beibehalten, aber trotzdem eigene Module oder Kernel signieren möchten. Er ermöglicht das Einrollen zusätzlicher Schlüssel, ohne die Firmware-Variablen direkt anfassen zu müssen:

# Neuen MOK-Schlüssel generieren
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.key \
    -out MOK.crt -nodes -days 3650 \
    -subj "/CN=Mein Unternehmen Secure Boot Schlüssel/"

# In DER-Format konvertieren (für mokutil benötigt)
openssl x509 -in MOK.crt -out MOK.der -outform DER

# MOK einrollen (erfordert Neustart und physischen Zugang)
mokutil --import MOK.der

# Nach dem Neustart erscheint der MokManager im Pre-Boot-Bereich
# Dort muss das Einrollen manuell bestätigt werden

# Eingerollte MOKs überprüfen
mokutil --list-enrolled

DKMS-Module mit Secure Boot

Dynamisch kompilierte Kernelmodule (DKMS) sind eine besondere Herausforderung — sie müssen nach jeder Kernel-Aktualisierung neu gebaut und signiert werden. Das kann schnell nervig werden, lässt sich aber gut automatisieren:

# DKMS-Signierungsskript erstellen
cat > /etc/dkms/sign_helper.sh <<'SCRIPT'
#!/bin/bash
/usr/lib/linux-kbuild-$(uname -r | cut -d. -f1-2)/scripts/sign-file \
    sha256 \
    /var/lib/shim-signed/mok/MOK.priv \
    /var/lib/shim-signed/mok/MOK.der \
    "$1"
SCRIPT
chmod +x /etc/dkms/sign_helper.sh

# In /etc/dkms/framework.conf eintragen:
# sign_tool="/etc/dkms/sign_helper.sh"

# Manuell ein einzelnes Modul signieren
kmodsign sha256 /var/lib/shim-signed/mok/MOK.priv \
    /var/lib/shim-signed/mok/MOK.der \
    /lib/modules/$(uname -r)/updates/dkms/vboxdrv.ko

# Überprüfen, ob ein Modul signiert ist
modinfo vboxdrv | grep sig

Die Microsoft-Zertifikat-Krise 2026

Jetzt wird's richtig spannend (und ein bisschen beunruhigend). Am 26. Juni 2026 läuft das Microsoft Corporation UEFI CA 2011-Zertifikat aus. Dieses Zertifikat ist die Grundlage dafür, dass nahezu alle Linux-Distributionen auf Hardware mit aktiviertem Secure Boot überhaupt booten können. Der Shim-Bootloader von Red Hat, Canonical, SUSE und Co. — alle mit diesem Microsoft-Zertifikat signiert.

Was bedeutet das konkret?

Nach dem Ablaufdatum werden Firmware-Implementierungen, die den Ablauf korrekt prüfen, die Shim-Signatur als ungültig betrachten. Das Tückische: Nicht alle UEFI-Implementierungen prüfen das Ablaufdatum — das Verhalten variiert je nach Hersteller und Firmware-Version. Das Ergebnis ist eine ziemlich fragmentierte Situation:

  • Einige Systeme werden nach einem Firmware-Update plötzlich nicht mehr booten
  • Andere Systeme ignorieren das Ablaufdatum und laufen einfach weiter
  • Neue Hardware ab Mitte 2026 wird wahrscheinlich nur noch das neue Zertifikat akzeptieren

Wie reagieren die Distributionen?

Red Hat / RHEL: Red Hat hat bereits mit RHEL 9.4 einen neuen Shim veröffentlicht, signiert mit dem Microsoft UEFI CA 2023-Zertifikat. Bestehende RHEL 8-Systeme bekommen Backport-Updates. Stellen Sie sicher, dass shim-x64 und grub2-efi-x64 aktuell sind.

Ubuntu / Canonical: Ubuntu 24.04 LTS und 22.04 LTS erhalten aktualisierte Shim-Pakete über die regulären Sicherheitsupdates. Canonical empfiehlt zusätzlich, die DBX-Datenbank nach dem Update zu aktualisieren, um alte Shim-Versionen zu widerrufen.

SUSE / openSUSE: SUSE hat einen cleveren Ansatz gewählt — ein doppelt signierter Shim, der sowohl das 2011er als auch das 2023er Zertifikat unterstützt. So soll der Übergang möglichst nahtlos klappen.

Empfohlene Maßnahmen für Administratoren

# 1. Aktuellen Shim-Status prüfen
rpm -q shim-x64     # RHEL/Fedora/SUSE
dpkg -l shim-signed  # Ubuntu/Debian

# 2. Prüfen, welche Zertifikate in der Firmware DB sind
efi-readvar -v db | grep "Microsoft"

# 3. Shim und GRUB aktualisieren
# RHEL/Fedora:
dnf update shim-x64 grub2-efi-x64

# Ubuntu/Debian:
apt update && apt upgrade shim-signed grub-efi-amd64-signed

# 4. DBX-Datenbank aktualisieren
fwupdmgr get-updates
fwupdmgr update

# 5. Nach dem Update verifizieren
mokutil --sb-state
bootctl status  # bei systemd-boot
Dringend empfohlen: Testen Sie alle Updates zuerst auf einem Staging-System! Ein fehlgeschlagenes Secure-Boot-Update kann dazu führen, dass ein System nicht mehr bootfähig ist — und dann brauchen Sie physischen Zugang für die Reparatur.

Measured Boot und TPM-Integration

Wie Measured Boot funktioniert

Secure Boot trifft eine binäre Entscheidung: Booten erlauben oder blockieren. Measured Boot geht einen entscheidenden Schritt weiter — jede Stufe des Bootvorgangs wird kryptografisch gemessen und in den Platform Configuration Registers (PCR) des TPM 2.0 gespeichert. Diese Messungen lassen sich später von lokalen oder entfernten Diensten überprüfen, um die Integrität des gesamten Bootvorgangs nachzuweisen.

Die wichtigsten PCR-Register und was sie bedeuten:

  • PCR 0: UEFI-Firmware-Code (BIOS/EFI)
  • PCR 1: UEFI-Firmware-Konfiguration
  • PCR 2: Option-ROMs (Erweiterungskarten)
  • PCR 3: Option-ROM-Konfiguration
  • PCR 4: MBR/Bootloader-Code (IPL-Code)
  • PCR 5: MBR/Bootloader-Konfiguration (IPL-Konfiguration)
  • PCR 7: Secure-Boot-Zustand und -Richtlinien
  • PCR 8-9: Kernel-Kommandozeile und initramfs (bei systemd-boot)
  • PCR 11: Unified Kernel Image Hash
  • PCR 12: Kernel-Kommandozeilenparameter (Overrides)
  • PCR 14: MOK-Zertifikate und Hashes

TPM-Messungen mit tpm2-tools überprüfen

# tpm2-tools installieren
# RHEL/Fedora:
dnf install tpm2-tools

# Ubuntu/Debian:
apt install tpm2-tools

# Alle PCR-Werte auslesen
tpm2_pcrread

# Nur bestimmte PCR-Register auslesen (SHA-256 Bank)
tpm2_pcrread sha256:0,1,4,7

# TPM-Eventlog auslesen und decodieren
tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements

# PCR-Werte gegen erwartete Referenzwerte prüfen
# (Nützlich für Remote Attestation)
tpm2_pcrread sha256:0,1,2,3,4,5,6,7 -o pcr_values.bin
sha256sum pcr_values.bin

Secure Boot und Measured Boot kombinieren: Defense in Depth

Erst die Kombination beider Mechanismen ergibt eine wirklich robuste Verteidigung:

  • Secure Boot verhindert die Ausführung unsignierter Software während des Bootvorgangs
  • Measured Boot protokolliert den genauen Zustand jeder Boot-Stufe — so lässt sich nachvollziehen, was tatsächlich geladen wurde
  • LUKS mit TPM-Bindung koppelt die Festplattenverschlüsselung an einen bekannten, integren Boot-Zustand
# LUKS-Schlüssel an PCR-Werte binden (systemd-cryptenroll)
systemd-cryptenroll --tpm2-device=auto \
    --tpm2-pcrs=0+1+4+7 \
    /dev/sda2

# Dies bewirkt, dass die Festplatte nur entschlüsselt wird,
# wenn Firmware, Konfiguration, Bootloader und Secure-Boot-Zustand
# den erwarteten Werten entsprechen

systemd Service-Härtung: Grundlagen

Warum systemd-Härtung entscheidend ist

Selbst wenn die Boot-Chain komplett abgesichert ist — was passiert, wenn ein laufender Dienst kompromittiert wird? Genau hier kommt systemd ins Spiel. Es bietet über 40 verschiedene Sicherheitsdirektiven, die den Zugriff eines Dienstes auf Systemressourcen granular einschränken. Im Kern implementieren diese Direktiven das Principle of Least Privilege auf Prozessebene und nutzen dafür Linux-Kernel-Mechanismen wie Namespaces, Capabilities, Seccomp und Cgroups.

systemd-analyze security: Der erste Schritt

Bevor Sie wild Direktiven in Ihre Unit-Dateien schreiben, verschaffen Sie sich erstmal einen Überblick. systemd-analyze security zeigt den Härtungsgrad aller aktiven Service-Units:

# Übersicht aller Services und ihre Sicherheitsbewertung
systemd-analyze security

# Detaillierte Analyse eines einzelnen Services
systemd-analyze security nginx.service

# Ausgabeformat: Jede Direktive wird bewertet
# EXPOSURE zeigt den Gesamtwert von 0.0 (sicher) bis 10.0 (unsicher)

# Beispielausgabe:
#   NAME                          DESCRIPTION                    EXPOSURE
#   nginx.service                 nginx web server               9.2 UNSAFE

Ein Exposure-Score von 9.2 — das ist schon ziemlich heftig. Unser Ziel: unter 2.0, was systemd als OK einstuft.

Wichtige systemd-Sicherheitsdirektiven

Dateisystem-Isolation

ProtectSystem=strict mountet das gesamte Dateisystem als schreibgeschützt. Der Dienst kann dann nur noch in explizit freigegebene Verzeichnisse schreiben:

[Service]
# Das gesamte Dateisystem ist nur lesbar
ProtectSystem=strict

# Explizit Schreibzugriff für bestimmte Verzeichnisse erlauben
ReadWritePaths=/var/log/nginx /var/cache/nginx /run/nginx

# Alternativ: Nur /usr und /boot schreibschützen
# ProtectSystem=full

# Oder: Nur /usr schreibschützen
# ProtectSystem=yes

ProtectHome=yes sperrt den Zugriff auf /home, /root und /run/user komplett. Mit ProtectHome=read-only wird nur der Schreibzugriff unterbunden, und ProtectHome=tmpfs legt ein leeres tmpfs über diese Verzeichnisse:

[Service]
ProtectHome=yes

PrivateTmp=yes erstellt einen privaten /tmp- und /var/tmp-Namespace. Andere Dienste und Benutzer können die temporären Dateien dieses Dienstes schlicht nicht sehen:

[Service]
PrivateTmp=yes

Kernel-Schutzmaßnahmen

ProtectKernelModules=yes verhindert, dass der Dienst Kernelmodule laden oder entladen kann — inklusive des Zugriffs auf /lib/modules:

[Service]
ProtectKernelModules=yes

ProtectKernelTunables=yes macht alle Kernel-Tunables in /proc/sys, /sys und ähnlichen virtuellen Dateisystemen schreibgeschützt. Damit kann ein kompromittierter Dienst keine Kernel-Parameter mehr verändern:

[Service]
ProtectKernelTunables=yes

ProtectKernelLogs=yes sperrt den Zugriff auf den Kernel-Log-Ring-Buffer (/dev/kmsg) und schützt so vor dem Auslesen sensibler Kernel-Meldungen:

[Service]
ProtectKernelLogs=yes

ProtectControlGroups=yes macht die Cgroup-Hierarchie unter /sys/fs/cgroup schreibgeschützt:

[Service]
ProtectControlGroups=yes

Privilegieneinschränkung

NoNewPrivileges=yes — das ist meiner Meinung nach eine der wichtigsten Direktiven überhaupt. Sie stellt sicher, dass der Prozess und alle Kindprozesse niemals neue Privilegien erlangen können, weder durch setuid-Binaries noch durch Capabilities:

[Service]
NoNewPrivileges=yes

RestrictSUIDSGID=yes verhindert, dass der Dienst SUID- oder SGID-Bits auf Dateien setzen kann:

[Service]
RestrictSUIDSGID=yes

CapabilityBoundingSet= begrenzt die verfügbaren Linux-Capabilities. Ein leerer Wert entfernt alle:

[Service]
# Nur die absolut notwendigen Capabilities erlauben
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_DAC_READ_SEARCH

# Oder: Alle Capabilities entfernen
# CapabilityBoundingSet=

Namespace-Isolation

RestrictNamespaces=yes verhindert die Erstellung neuer Linux-Namespaces. Das betrifft User-, PID-, Network- und Mount-Namespaces — und erschwert Container-Ausbrüche erheblich:

[Service]
RestrictNamespaces=yes

# Alternativ: Nur bestimmte Namespaces erlauben
# RestrictNamespaces=~user pid net

Systemaufruf-Filterung

SystemCallFilter= nutzt Seccomp, um die verfügbaren Systemaufrufe einzuschränken. systemd bietet praktische vordefinierte Gruppen:

[Service]
# Nur grundlegende Systemaufrufe und Netzwerk-I/O erlauben
SystemCallFilter=@system-service

# Gefährliche Systemaufrufe explizit verbieten
SystemCallFilter=~@mount @clock @debug @module @raw-io @reboot @swap

# Verfügbare Systemaufruf-Gruppen anzeigen:
# systemd-analyze syscall-filter

Dateisystem-Zugriffskontrolle

ReadWritePaths=, ReadOnlyPaths= und InaccessiblePaths= geben granulare Kontrolle über den Dateisystemzugriff:

[Service]
ProtectSystem=strict
ReadWritePaths=/var/lib/myapp /var/log/myapp
ReadOnlyPaths=/etc/myapp
InaccessiblePaths=/home /root /var/lib/other-sensitive-app

Dynamische Benutzer

DynamicUser=yes weist dem Dienst einen transienten, dynamisch zugewiesenen Benutzer zu. Dieser existiert nur während der Laufzeit — keine persistente Spur auf dem System:

[Service]
DynamicUser=yes

# Persistenter Zustandsspeicher für DynamicUser
StateDirectory=myapp
CacheDirectory=myapp
LogsDirectory=myapp
Hinweis: DynamicUser=yes impliziert automatisch ProtectSystem=strict, ProtectHome=read-only, PrivateTmp=yes und RemoveIPC=yes. Ehrlich gesagt ist es eine der wirkungsvollsten einzelnen Härtungsmaßnahmen, die systemd bietet.

Praxisbeispiel: Einen Webserver-Dienst härten

Vorher: Standard-nginx-Unit-Datei

So sieht eine typische, ungehärtete nginx-Service-Unit aus — und das ist leider bei vielen Installationen genau das, was man in der Praxis vorfindet:

# /etc/systemd/system/nginx.service (VORHER - UNGEHÄRTET)
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
# Sicherheitsbewertung VOR der Härtung
systemd-analyze security nginx.service

# Ausgabe (gekürzt):
#   Overall exposure level for nginx.service: 9.2 UNSAFE

Nachher: Vollständig gehärtete Unit-Datei

Und so sieht das Ganze nach der Härtung aus. Die Unterschiede sind beachtlich:

# /etc/systemd/system/nginx.service (NACHHER - GEHÄRTET)
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID

# === Dateisystem-Isolation ===
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/log/nginx /var/cache/nginx /run

# === Kernel-Schutz ===
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes

# === Netzwerk ===
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6

# === Privilegien ===
NoNewPrivileges=yes
RestrictSUIDSGID=yes
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_DAC_READ_SEARCH CAP_SETUID CAP_SETGID
AmbientCapabilities=CAP_NET_BIND_SERVICE

# === Namespaces und Systemaufrufe ===
RestrictNamespaces=yes
SystemCallFilter=@system-service
SystemCallFilter=~@mount @debug @module @raw-io @reboot @swap @clock
SystemCallArchitectures=native

# === Verschiedenes ===
LockPersonality=yes
MemoryDenyWriteExecute=yes
ProtectHostname=yes
ProtectClock=yes
ProtectProc=invisible
ProcSubset=pid
RestrictRealtime=yes
PrivateDevices=yes
DevicePolicy=closed
UMask=0077

[Install]
WantedBy=multi-user.target
# Sicherheitsbewertung NACH der Härtung
systemd-analyze security nginx.service

# Ausgabe (gekürzt):
#   Overall exposure level for nginx.service: 1.8 OK

# Service neu laden und testen
systemctl daemon-reload
systemctl restart nginx.service
systemctl status nginx.service

# Funktionalität verifizieren
curl -I http://localhost

Von 9.2 auf 1.8 — das sind über 80 Prozent Reduktion. Und das Beste: nginx läuft weiterhin einwandfrei. Der Dienst hat nur drastisch eingeschränkte Möglichkeiten, das System zu kompromittieren, falls er tatsächlich angegriffen wird.

Schrittweises Vorgehen bei der Härtung

Beim Härten produktiver Dienste sollten Sie nicht alles auf einmal umstellen. Ein schrittweises Vorgehen hat sich in der Praxis bewährt:

  1. Starten Sie mit systemd-analyze security dienstname.service, um den Ist-Zustand zu ermitteln
  2. Fügen Sie zunächst die risikoarmen Direktiven hinzu: ProtectHome=yes, ProtectKernelModules=yes, ProtectKernelTunables=yes, NoNewPrivileges=yes
  3. Testen Sie nach jeder Änderung die Funktionalität gründlich
  4. Fügen Sie dann restriktivere Direktiven wie ProtectSystem=strict mit passenden ReadWritePaths= hinzu
  5. Implementieren Sie zuletzt SystemCallFilter= und CapabilityBoundingSet= — die verursachen am ehesten Probleme
  6. Nutzen Sie journalctl -u dienstname.service, um auf seccomp-Fehler oder Permission-Denied-Meldungen zu achten

Fortgeschrittene Techniken

Secure Boot kombiniert mit dm-verity: Unveränderliches Root-Dateisystem

dm-verity bietet kryptografische Integritätsüberprüfung für Block-Devices auf Basis von Merkle-Bäumen. Kombiniert mit Secure Boot entsteht eine lückenlose Vertrauenskette vom Einschalten bis zum laufenden Root-Dateisystem — das ist wirklich das Nonplusultra in Sachen Boot-Integrität:

# dm-verity Hash-Baum für ein Root-Device erstellen
veritysetup format /dev/sda3 /dev/sda4

# Ausgabe enthält den Root-Hash, z.B.:
# Root hash: 4a2e8b3f...

# dm-verity Device aktivieren
veritysetup open /dev/sda3 verified-root /dev/sda4 \
    4a2e8b3f...  # Root-Hash hier einfügen

# Das verifizierte Device ist nun unter /dev/mapper/verified-root verfügbar
mount -o ro /dev/mapper/verified-root /mnt

# Den Root-Hash in die Kernel-Kommandozeile einbetten:
# root=/dev/dm-0 dm-mod.create="verified-root,,0,ro,0 $(blockdev --getsz /dev/sda3) verity 1 /dev/sda3 /dev/sda4 4096 4096 $(expr $(blockdev --getsz /dev/sda3) / 8) 1 sha256 ROOT_HASH_HIER salt-"

# Für Produktionsumgebungen: Den Root-Hash im UKI einbetten
# (siehe nächster Abschnitt)

In dieser Konfiguration wird jeder einzelne Block des Root-Dateisystems beim Lesen verifiziert. Manipulation wird sofort erkannt und führt zu einem I/O-Fehler. Rootkits haben so keine Chance, Systemdateien unbemerkt zu ändern.

systemd-creds: Verschlüsselte Dienst-Credentials

systemd-creds ist ein Feature, das meiner Erfahrung nach noch viel zu wenig Beachtung bekommt. Es ermöglicht die verschlüsselte Speicherung von Dienstzugangsdaten, gebunden an den TPM und die spezifische Service-Unit:

# Ein Credential verschlüsseln (an TPM und Host-ID gebunden)
systemd-creds encrypt --name=db-password \
    --with-key=tpm2 \
    - /etc/credstore.encrypted/myapp-db-password.cred \
    <<<"SuperGeheimesPasswort123"

# In der Service-Unit auf das Credential zugreifen:
# [Service]
# SetCredentialEncrypted=db-password:/etc/credstore.encrypted/myapp-db-password.cred

# Im Dienst ist das Credential dann unter diesem Pfad verfügbar:
# $CREDENTIALS_DIRECTORY/db-password

# Beispiel: Vollständige Service-Unit mit Credentials
cat > /etc/systemd/system/myapp.service <<'EOF'
[Service]
Type=simple
ExecStart=/usr/local/bin/myapp
SetCredentialEncrypted=db-password:/etc/credstore.encrypted/myapp-db-password.cred
SetCredentialEncrypted=api-key:/etc/credstore.encrypted/myapp-api-key.cred

# Das Credential ist im Dienst verfügbar als:
# /run/credentials/myapp.service/db-password
# /run/credentials/myapp.service/api-key
EOF

# Alle verfügbaren Credentials auflisten
systemd-creds list

Der entscheidende Vorteil gegenüber Umgebungsvariablen oder Klartext-Konfigurationsdateien: Die Credentials können nur auf dem spezifischen Host, mit dem spezifischen TPM und für den spezifischen Dienst entschlüsselt werden. Selbst wenn ein Angreifer die verschlüsselte Datei kopiert — auf einem anderen System ist sie wertlos.

Unified Kernel Images (UKI): Manipulationssicherer Boot

Unified Kernel Images bündeln Kernel, initramfs, Kernel-Kommandozeile und optional weitere Ressourcen in einer einzigen, signierten EFI-Binary. Das beseitigt gleich mehrere Angriffsvektoren der traditionellen Boot-Chain auf einen Schlag:

# UKI manuell mit ukify erstellen
/usr/lib/systemd/ukify build \
    --linux=/boot/vmlinuz-6.12 \
    --initrd=/boot/initramfs-6.12.img \
    --cmdline="root=UUID=xxxx ro quiet" \
    --os-release=@/etc/os-release \
    --splash=/usr/share/systemd/bootctl/splash-arch.bmp \
    --secureboot-private-key=/usr/share/secureboot/keys/db/db.key \
    --secureboot-certificate=/usr/share/secureboot/keys/db/db.pem \
    --pcr-private-key=/usr/share/secureboot/keys/tpm2-pcr-private.pem \
    --pcr-banks=sha256 \
    --output=/boot/EFI/Linux/arch-6.12.efi

# UKI-Erstellung automatisieren via /etc/kernel/install.d/
# oder über die Konfiguration in /etc/kernel/uki.conf

# kernel-install für automatische UKI-Erstellung konfigurieren
cat > /etc/kernel/install.conf <<'EOF'
layout=uki
initrd_generator=dracut
uki_generator=ukify
EOF

# UKI-spezifische Konfiguration
cat > /etc/kernel/uki.conf <<'EOF'
[UKI]
SecureBootSigningTool=/usr/bin/sbsign
SecureBootPrivateKey=/usr/share/secureboot/keys/db/db.key
SecureBootCertificate=/usr/share/secureboot/keys/db/db.pem
PCRPKey=/usr/share/secureboot/keys/tpm2-pcr-public.pem
EOF

# Bei der nächsten Kernelinstallation wird automatisch ein
# signiertes UKI erstellt und in der ESP abgelegt

Die Vorteile von UKIs auf einen Blick:

  • Keine separate Kernel-Kommandozeile: Die Kommandozeile ist im UKI eingebettet und signiert. Ein Angreifer kann keine Boot-Parameter wie init=/bin/bash einschleusen.
  • Kein separater Bootloader nötig: Das UKI wird direkt von der Firmware oder systemd-boot geladen. GRUB wird überflüssig — und damit auch dessen Angriffsfläche.
  • TPM-PCR-Vorhersage: Die erwarteten PCR-Werte lassen sich im Voraus berechnen und für LUKS-Entschlüsselung nutzen.
  • Atomare Updates: Ein neuer Kernel wird als einzelne Datei ausgeliefert — entweder ganz oder gar nicht.

Automatisierung und Compliance

OpenSCAP für Boot-Chain- und Service-Härtungsüberprüfung

OpenSCAP ist das Standard-Tool für automatisierte Compliance-Prüfungen unter Linux und unterstützt Profile wie CIS Benchmarks und DISA STIGs. Für regelmäßige Audits ist es quasi unverzichtbar:

# OpenSCAP installieren
# RHEL/Fedora:
dnf install openscap-scanner scap-security-guide

# Ubuntu/Debian:
apt install libopenscap8 ssg-debian ssg-ubuntu

# Verfügbare Profile anzeigen
oscap info /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

# System gegen CIS-Benchmark scannen
oscap xccdf eval \
    --profile cis_server_l1 \
    --results scan-results.xml \
    --report scan-report.html \
    /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

# Bericht im Browser öffnen
xdg-open scan-report.html

Benutzerdefiniertes Audit-Skript für die gesamte Flotte

Für eine umfassende Prüfung von Boot-Chain-Sicherheit und Service-Härtung über viele Server hinweg habe ich ein Skript zusammengestellt, das Sie als Ausgangspunkt verwenden können:

#!/bin/bash
# boot-and-service-audit.sh
# Umfassendes Audit-Skript für Boot-Chain und Service-Härtung

set -euo pipefail

REPORT_FILE="/var/log/security-audit-$(date +%Y%m%d-%H%M%S).json"
HOSTNAME=$(hostname -f)
ERRORS=0

echo "{ \"hostname\": \"${HOSTNAME}\", \"timestamp\": \"$(date -Is)\", \"checks\": [" > "${REPORT_FILE}"

# --- Boot-Chain Checks ---

# 1. Secure Boot Status
SB_STATE=$(mokutil --sb-state 2>/dev/null || echo "nicht verfügbar")
if echo "${SB_STATE}" | grep -q "enabled"; then
    SB_OK="true"
else
    SB_OK="false"
    ((ERRORS++))
fi
echo "  {\"check\": \"secure_boot\", \"status\": ${SB_OK}, \"detail\": \"${SB_STATE}\"}," >> "${REPORT_FILE}"

# 2. TPM 2.0 Verfügbarkeit
if [ -c /dev/tpm0 ]; then
    TPM_OK="true"
    TPM_DETAIL="TPM 2.0 device vorhanden"
else
    TPM_OK="false"
    TPM_DETAIL="Kein TPM-Device gefunden"
    ((ERRORS++))
fi
echo "  {\"check\": \"tpm_available\", \"status\": ${TPM_OK}, \"detail\": \"${TPM_DETAIL}\"}," >> "${REPORT_FILE}"

# 3. Kernel-Lockdown-Modus
LOCKDOWN=$(cat /sys/kernel/security/lockdown 2>/dev/null || echo "nicht verfügbar")
if echo "${LOCKDOWN}" | grep -q "\[integrity\]\|confidentiality"; then
    LD_OK="true"
else
    LD_OK="false"
    ((ERRORS++))
fi
echo "  {\"check\": \"kernel_lockdown\", \"status\": ${LD_OK}, \"detail\": \"${LOCKDOWN}\"}," >> "${REPORT_FILE}"

# --- Service-Härtungs-Checks ---

# 4. Alle Services mit hohem Exposure-Score finden
echo "  {\"check\": \"service_hardening\", \"unsafe_services\": [" >> "${REPORT_FILE}"
FIRST=true
while IFS= read -r line; do
    SERVICE=$(echo "$line" | awk '{print $1}')
    SCORE=$(echo "$line" | awk '{print $2}')
    # Score > 5.0 als unsicher betrachten
    SCORE_INT=$(echo "$SCORE" | cut -d. -f1)
    if [ "${SCORE_INT}" -ge 5 ] 2>/dev/null; then
        if [ "${FIRST}" = true ]; then
            FIRST=false
        else
            echo "," >> "${REPORT_FILE}"
        fi
        echo -n "    {\"service\": \"${SERVICE}\", \"score\": \"${SCORE}\"}" >> "${REPORT_FILE}"
        ((ERRORS++))
    fi
done < <(systemd-analyze security --no-pager 2>/dev/null | tail -n +2 | head -50)
echo "" >> "${REPORT_FILE}"
echo "  ]}," >> "${REPORT_FILE}"

# 5. Shim-Version prüfen
SHIM_VER=$(rpm -q shim-x64 2>/dev/null || dpkg -l shim-signed 2>/dev/null | grep shim | awk '{print $3}' || echo "nicht installiert")
echo "  {\"check\": \"shim_version\", \"version\": \"${SHIM_VER}\"}" >> "${REPORT_FILE}"

# Abschluss
echo "], \"total_errors\": ${ERRORS} }" >> "${REPORT_FILE}"

echo "Audit abgeschlossen. ${ERRORS} Probleme gefunden."
echo "Bericht gespeichert unter: ${REPORT_FILE}"

# Exit-Code spiegelt gefundene Probleme wider
exit $(( ERRORS > 0 ? 1 : 0 ))

Integration in CI/CD-Pipelines

Für Infrastructure-as-Code-Umgebungen gehören Sicherheitsprüfungen in die CI/CD-Pipeline — das ist keine Kür, sondern Pflicht. Hier ein Beispiel mit GitLab CI:

# .gitlab-ci.yml - Sicherheits-Checks für systemd Service-Units
stages:
  - lint
  - security
  - deploy

systemd-unit-lint:
  stage: lint
  image: registry.example.com/systemd-toolbox:latest
  script:
    - |
      # Alle Service-Unit-Dateien syntaktisch prüfen
      for unit in deploy/systemd/*.service; do
        echo "Prüfe ${unit}..."
        systemd-analyze verify "${unit}" || exit 1
      done

service-hardening-check:
  stage: security
  image: registry.example.com/systemd-toolbox:latest
  script:
    - |
      # Temporäre systemd-Instanz für die Analyse starten
      for unit in deploy/systemd/*.service; do
        SERVICE_NAME=$(basename "${unit}")
        cp "${unit}" /etc/systemd/system/
        systemctl daemon-reload

        # Sicherheitsbewertung prüfen
        SCORE=$(systemd-analyze security "${SERVICE_NAME}" 2>/dev/null \
            | grep "Overall exposure" \
            | grep -oP '[\d.]+')

        echo "${SERVICE_NAME}: Exposure Score = ${SCORE}"

        # Pipeline fehlschlagen lassen, wenn Score > 4.0
        if (( $(echo "${SCORE} > 4.0" | bc -l) )); then
          echo "FEHLER: ${SERVICE_NAME} hat einen zu hohen Exposure Score!"
          systemd-analyze security "${SERVICE_NAME}"
          exit 1
        fi
      done
  allow_failure: false

secure-boot-verification:
  stage: security
  tags:
    - bare-metal  # Benötigt physischen Zugang zu UEFI
  script:
    - |
      # Alle Kernel- und Bootloader-Binaries verifizieren
      sbctl verify
      if [ $? -ne 0 ]; then
        echo "FEHLER: Unsignierte Boot-Dateien gefunden!"
        exit 1
      fi
    - |
      # UKI-Integrität prüfen
      for uki in /boot/EFI/Linux/*.efi; do
        sbverify --cert /usr/share/secureboot/keys/db/db.pem "${uki}" || exit 1
        echo "OK: ${uki} korrekt signiert"
      done

Ansible-Playbook zur flottenweiten Service-Härtung

Wenn Sie die Härtung über eine ganze Serverflotte ausrollen wollen, ist Ansible Ihr bester Freund. Hier ein Playbook als Ausgangspunkt:

# harden-systemd-services.yml
---
- name: systemd Services härten
  hosts: all
  become: yes
  vars:
    hardening_directives:
      - ProtectSystem=strict
      - ProtectHome=yes
      - PrivateTmp=yes
      - NoNewPrivileges=yes
      - ProtectKernelModules=yes
      - ProtectKernelTunables=yes
      - ProtectKernelLogs=yes
      - ProtectControlGroups=yes
      - RestrictNamespaces=yes
      - RestrictSUIDSGID=yes
      - LockPersonality=yes
      - ProtectHostname=yes
      - ProtectClock=yes

    services_to_harden:
      - name: nginx
        extra_readwrite:
          - /var/log/nginx
          - /var/cache/nginx
          - /run
        capabilities:
          - CAP_NET_BIND_SERVICE
          - CAP_DAC_READ_SEARCH

      - name: postgresql
        extra_readwrite:
          - /var/lib/postgresql
          - /var/log/postgresql
          - /run/postgresql
        capabilities:
          - CAP_DAC_READ_SEARCH

  tasks:
    - name: Erstelle systemd Override-Verzeichnis
      file:
        path: "/etc/systemd/system/{{ item.name }}.service.d"
        state: directory
        mode: '0755'
      loop: "{{ services_to_harden }}"

    - name: Schreibe Härtungs-Override-Datei
      template:
        src: hardening-override.conf.j2
        dest: "/etc/systemd/system/{{ item.name }}.service.d/hardening.conf"
        mode: '0644'
      loop: "{{ services_to_harden }}"
      notify: reload systemd

    - name: Prüfe Service-Exposure-Score
      command: "systemd-analyze security {{ item.name }}.service"
      loop: "{{ services_to_harden }}"
      register: security_scores
      changed_when: false

  handlers:
    - name: reload systemd
      systemd:
        daemon_reload: yes

Fazit und Checkliste

Die Absicherung eines Linux-Systems ist kein einzelner Schalter, den man umlegt — es ist ein durchgängiger Prozess, der beim ersten Firmware-Befehl beginnt und sich bis zur Ausführung einzelner Dienste erstreckt. Was wir in diesem Leitfaden durchgegangen sind, bildet zusammen eine mehrstufige Verteidigungsstrategie (Defense in Depth). Das Versagen einer einzelnen Schicht führt dabei nicht zum Totalverlust.

Besonders dringend ist 2026 die Vorbereitung auf den Ablauf des Microsoft UEFI CA 2011-Zertifikats. Wer hier zu spät dran ist, riskiert ernsthafte Betriebsunterbrechungen. Genauso sollte die systematische Härtung aller systemd-Service-Units ab sofort zum Standard in jedem Deployment-Prozess gehören.

Vollständige Sicherheits-Checkliste

Boot-Chain-Sicherheit:

  • UEFI Secure Boot ist aktiviert und verifiziert (mokutil --sb-state)
  • Eigene Secure-Boot-Schlüssel sind erstellt und eingerollt (oder die Distributions-Schlüssel sind aktuell)
  • Alle Kernel-Images und Bootloader sind kryptografisch signiert
  • Die DBX-Datenbank ist aktuell und widerruft bekannte unsichere Bootloader
  • Shim und GRUB sind auf die neueste Version aktualisiert (Microsoft UEFI CA 2023-Kompatibilität)
  • DKMS-Module werden automatisch nach jedem Build signiert
  • Ein Rollback-Plan für fehlgeschlagene Secure-Boot-Updates existiert

TPM und Measured Boot:

  • TPM 2.0 ist aktiviert und vom System erkannt
  • Measured Boot ist aktiv und PCR-Werte werden korrekt geschrieben
  • LUKS-Volumes sind an TPM-PCR-Werte gebunden (mindestens PCR 0, 1, 4, 7)
  • PCR-Referenzwerte werden dokumentiert und bei Updates aktualisiert
  • systemd-creds wird für sensitive Dienstzugangsdaten verwendet

Unified Kernel Images:

  • UKIs werden für alle produktiven Systeme erstellt
  • Die Kernel-Kommandozeile ist im UKI eingebettet (keine externe Manipulation möglich)
  • ukify und kernel-install sind für automatische UKI-Erstellung konfiguriert
  • UKIs sind mit den eigenen Secure-Boot-Schlüsseln signiert

systemd Service-Härtung:

  • Alle produktiven Services haben einen Exposure-Score unter 4.0
  • Kritische Direktiven sind gesetzt: ProtectSystem=strict, NoNewPrivileges=yes, PrivateTmp=yes
  • Kernel-Schutzdirektiven sind aktiviert: ProtectKernelModules, ProtectKernelTunables, ProtectKernelLogs
  • SystemCallFilter= ist auf die minimal notwendigen Systemaufrufe beschränkt
  • CapabilityBoundingSet= enthält nur die wirklich benötigten Capabilities
  • ReadWritePaths= beschränkt den Schreibzugriff auf die notwendigen Verzeichnisse
  • DynamicUser=yes wird wo immer möglich eingesetzt
  • RestrictNamespaces=yes und RestrictAddressFamilies= sind konfiguriert

Automatisierung und Compliance:

  • OpenSCAP-Scans laufen regelmäßig (mindestens wöchentlich)
  • Das Boot-Chain-Audit-Skript wird auf allen Systemen ausgeführt
  • CI/CD-Pipelines prüfen Exposure-Scores vor dem Deployment
  • Ansible oder ein vergleichbares Tool rollt Härtungsmaßnahmen flottenübergreifend aus
  • Abweichungen von der Baseline werden automatisch erkannt und gemeldet
  • Alle Sicherheitsmaßnahmen sind als Code versioniert und reproduzierbar
Zum Schluss: Sicherheit ist kein einmaliges Projekt, sondern ein fortlaufender Prozess. Die Bedrohungslandschaft entwickelt sich ständig weiter — und Ihre Verteidigung muss das auch tun. Planen Sie regelmäßige Reviews Ihrer Boot-Chain-Konfiguration und Service-Härtung ein, bleiben Sie bei neuen Kernel-CVEs und Firmware-Updates am Ball. Die Werkzeuge und Techniken aus diesem Leitfaden geben Ihnen das Fundament, um Ihre Linux-Infrastruktur auch 2026 und darüber hinaus wirksam zu schützen.
Über den Autor Editorial Team

Our team of expert writers and editors.