Härtung von systemd-Diensten
(roguesecurity.dev)- systemd bietet leistungsstarke Funktionen zur Dienstverwaltung, doch die Standardeinstellungen sind eher auf Benutzerfreundlichkeit als auf Sicherheit optimiert, weshalb zusätzliche Härtungsoptionen angewendet werden sollten
- Mit dem Befehl
systemd-analyze securitylassen sich die Sicherheits-Expositionswerte aller oder einzelner Dienste analysieren und priorisieren - Es gibt verschiedene Sicherheitsoptionen, die auf Dienstebene angewendet werden können; sie lassen sich individuell über
/etc/systemd/system/ServiceName.service.d/override.confusw. anpassen - Zu den wichtigsten Optionen gehören
ProtectSystem,PrivateTmp,NoNewPrivileges,SystemCallFilter,MemoryDenyWriteExecuteund weitere Einstellungen, die Prozessrechte und den Zugriff auf Ressourcen einschränken - Statt perfekte Sicherheit anzustreben, lässt sich das Risiko wirksam senken, indem man nach außen exponierte Dienste zuerst härtet; auch in Self-Hosting-Umgebungen ist der Effekt groß
Überblick über systemd
- systemd bietet bei der Dienstverwaltung einen sehr ausgereiften und robusten Ansatz
- Allerdings sind die Standardeinstellungen locker gehalten, weil sofortige Nutzbarkeit höher gewichtet wird als Sicherheit
- Dieses Dokument stellt verschiedene Härtungsoptionen vor, die auf systemd-Service-Units und podman quadlets angewendet werden können, um die Wahrscheinlichkeit einer Kompromittierung zu senken und im Fall eines Vorfalls den Schaden zu begrenzen
- Es ist kein Leitfaden zur pauschalen Anwendung auf alle Dienste; je nach Eigenschaften und Anforderungen eines Dienstes sind individuelle Tests, Log-Prüfungen und Anpassungen erforderlich
- Die Verantwortung für die Sicherheit der Infrastruktur liegt vollständig beim Betreiber; dieses Dokument ist ein Hilfsmittel zur Orientierung
Sicherheitsanalyse von systemd
- Mit dem Befehl
systemd-analyze securitylässt sich der Sicherheitsstatus aller Dienste prüfen oder die Detailkonfiguration eines bestimmten Dienstes (z. B.sshd.service) analysieren- Die Ausgabe enthält Prüfergebnis, Funktionsname, Beschreibung und den Exposure-Wert; je höher der Exposure-Wert, desto größer das Risiko
- Sicherheitsoptionen können im Abschnitt
[Service](systemd) oder[Container](podman quadlet) zusätzlich gesetzt werden - Empfohlen wird die Erstellung einer Override-Datei über
systemctl edit ServiceName.service; bei Fehlern sollten die benötigten Berechtigungen geprüft und angepasst werden
Sicherheitsoptionen für Dienste
- systemd bietet verschiedene Schlüsselwörter für Sicherheitsoptionen, die sich über
man systemd.exec 5,man capabilities 7usw. nachschlagen lassen - Typische sicherheitsrelevante Optionen
ProtectSystem→ beschränkt das Dateisystem auf schreibgeschützten ZugriffProtectHome→ blockiert den Zugriff auf/home,/root,/run/userPrivateDevices→ blockiert den Zugriff auf physische Geräte und erlaubt nur virtuelle Geräte wie/dev/nullProtectKernelTunables,ProtectKernelModules,ProtectKernelLogs→ blockieren den Zugriff auf Kernel-RessourcenNoNewPrivileges→ verhindert den Erwerb neuer Rechte über setuid/setgid usw.MemoryDenyWriteExecute→ verhindert die gleichzeitige Nutzung von beschreibbarem und ausführbarem Speicher; kann bei einigen JIT-Sprachen Probleme verursachenSystemCallFilter→ beschränkt zulässige System-Calls; bei Verstößen kann der Prozess beendet oderEPERMzurückgegeben werden
Erläuterung der einzelnen Optionen
- ProtectSystem: Mit der Einstellung
strictwird das gesamte Dateisystem schreibgeschützt eingehängt; für/dev,/proc,/syssind separate Schutzoptionen nötig - ReadWritePaths: Erlaubt das Schreiben wieder nur auf bestimmten Pfaden
- ProtectHome: Blockiert den Zugriff auf
/home,/root,/run/user - PrivateDevices: Deaktiviert den Zugriff auf physische Geräte und erlaubt nur Pseudo-Geräte wie
/dev/null - ProtectKernelTunables: Behandelt
/procund/sysals schreibgeschützt - ProtectControlGroups: Erlaubt nur schreibgeschützten Zugriff auf cgroups
- ProtectKernelModules: Verbietet das explizite Laden von Kernel-Modulen
- ProtectKernelLogs: Beschränkt den Zugriff auf den Kernel-Log-Puffer
- ProtectProc: Mit der Einstellung
invisiblewerden Prozesse anderer Benutzer in/proc/verborgen - ProcSubset: Blendet in
/procInhalte aus, die nicht zu bestimmten PID-bezogenen Einträgen gehören - NoNewPrivileges: Verhindert neue Privilegieneskalation über setuid, setgid und Dateisystem-Capabilities
- ProtectClock: Blockiert Schreibzugriffe auf System- und Hardware-Uhr
- SystemCallArchitectures: Mit
nativesind nur native Syscalls wie x86-64 erlaubt - RestrictNamespaces: Beschränkt containerbezogene Namespaces
- RestrictSUIDSGID: Verhindert das Setzen der Dateibits setuid und setgid
- LockPersonality: Verhindert Änderungen der Ausführungsdomäne (nur für ältere Anwendungen relevant)
- RestrictRealtime: Beschränkt Echtzeit-Scheduling (nur für bestimmte Spezialdienste nötig)
- RestrictAddressFamilies: Beschränkt erlaubte Socket-Adressfamilien (z. B. AF_INET, AF_INET6, AF_UNIX usw.)
- MemoryDenyWriteExecute: Verhindert das zusätzliche Anlegen von Speicherbereichen mit Schreib- und Ausführungsrechten zugleich (Vorsicht bei Diensten mit JIT)
- ProtectHostname: Verbietet die Verwendung der Syscalls
sethostnameundsetdomainname - SystemCallFilter: Erlaubt dienstspezifische Regeln zum Zulassen oder Sperren von Syscalls und eine feingranulare Filterung
- Gruppen, einzelne Syscalls sowie Allow-/Deny-Strategien lassen sich anpassen
- Bei Verstößen kann statt eines Prozessabbruchs auch die Rückgabe eines Fehlercodes wie
EPERMkonfiguriert werden - Die vollständige Liste ist über
systemd-analyze syscall-filteroderman systemd.exec(5)einsehbar - Mit dem Präfix
~lässt sich eine gesamte Liste negieren (z. B.CapabilityBoundingSet=~CAP_SETUIDusw.)
Vorgehen zum Anpassen von SystemCallFilter-Beschränkungen
- Mit
auditdlässt sich beim Fehlschlagen eines Dienstes im Log prüfen, welcher Syscall blockiert wurdesudo ausearch -i -m SECCOMP -ts recentausführen und anschließend den Syscall-Wert prüfen- Den betreffenden Syscall oder die zugehörige Gruppe zu
SystemCallFilterhinzufügen, um das Problem schrittweise zu beheben
Priorisierung der Härtung und Betriebstipps
- Es ist nicht nötig, alles auf jeden Dienst anzuwenden
- Entscheidend sind Bedrohungsmodell und Risikomanagement; insbesondere nach außen exponierte Dienste (httpd, nginx, ssh usw.) sollten zwingend berücksichtigt werden
- Auch bei benutzerdefinierten Kommandos und Timer-Units (als Ersatz für cron) ist eine frühzeitige Anwendung wirksam
- Je weniger komplex ein Dienst ist, desto eher ist eine feine Abstimmung möglich
Checkliste: empfohlene Kombination von Sicherheitsoptionen (Priorität für die erste Anwendung)
ProtectSystem=strictPrivateTmp=yesProtectHome=yesoderProtectHome=tmpfsProtectClock=yes,ProtectKernelLogs=yes,ProtectKernelModules=yesRestrictSUIDGUID=yesUMask=0077LockPersonality=yesRestrictRealtime=yesMemoryDenyWriteExecute=yesDynamicUser=yesoderUserauf einen bestimmten Nicht-Root-Benutzer setzen
- Diese Punkte sind in der Regel eine Kombination, die sich für Dienste fast ohne Beeinträchtigung verwenden lässt
- Wenn zusätzlich Syscall-Filterung (
SystemCallFilter) eingesetzt werden soll, sind detaillierte Tests erforderlich
Beispielkonfiguration für Traefik
- Ein Beispiel für einen containerbasierten Traefik-Dienst, der als systemd quadlet läuft und viele Sicherheitsoptionen anwendet
- Verwendet werden u. a.
ProtectSystem=full,ProtectHome=yes,SystemCallFilter=@system-service @mount @privileged - Mit
CapabilityBoundingSet=~CAP_SETUID CAP_SETPCAPwerden bestimmte Rechte entfernt - Mit
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINKusw. wird der Netzwerkzugriff eingeschränkt
- Verwendet werden u. a.
Fazit
- Die Härtungsoptionen von systemd sind für Administratoren von Unix-artigen Systemen ein praktisches Werkzeug, das in keinen Werkzeugkasten fehlen muss
- Sie sind kein perfektes Sicherheitsmittel, sondern ein Werkzeug zur Risikoreduzierung; es ist nicht nötig, wahllos auf alle Dienste Sicherheitseinstellungen anzuwenden
- Besonders für Administratoren in Self-Hosting-Umgebungen kann der Einsatz die Sicherheitslage deutlich verbessern
- Mit dem Grundsatz „Praktikabilität vor Perfektion“ wird empfohlen, die Optionen zumindest teilweise und passend zu Arbeitsabläufen und Umgebung einzusetzen
1 Kommentare
Hacker-News-Kommentare
Ich finde es interessant, dass sich automatisiertes Hardening von systemd-Services per
strace-Profiling umsetzen lässt.https://github.com/desbma/shh
Ich habe eine gute Methode gefunden: Im Beispiel wurde zwar
ProtectSystem=nicht verwendet, aber mitTemporaryFileSystem=/:ro, BindReadOnly=/usr/bin/binary /lib /lib64 /usr/lib usr/lib64kann man nur die gewünschten Binärdateien und die Pfade einschließen, die lesbar sein sollen.
ProtectSystem=ist derzeit mit diesem Verhalten nicht kompatibel.Mehr dazu hier.
Ich denke, dieser Ansatz kann problematisch für Services sein, die bei Fehlern zusätzliche Aktionen ausführen müssen, etwa E-Mails versenden.
Im Vergleich zu dem gestrigen Beitrag über systemd-Hardening ist dieser hier deutlich praxisnäher und enthält viele gute Tipps, die sich sofort anwenden lassen.
Ich hatte gestern in den Kommentaren versucht, praktischere Beispiele zu geben, und der heutige Beitrag fasst das alles sehr gut zusammen und zeigt, wie man Isolation und Sicherheit mit systemd schnell und einfach verbessern kann.
Ich halte das für einen hervorragenden Artikel.
Zur Referenz hier auch noch der gestrige Beitrag.
https://us.jlcarveth.dev/post/hardening-systemd.md
https://news.ycombinator.com/item?id=44928504
In manchen Browsern ist die Seite wegen Zertifikatsfehlern gar nicht erreichbar.
Danke fürs Teilen.
Mit
systemd-analyzezusammen mit dem Flag--userkann man die Sicherheit von systemd-Benutzereinheiten prüfen (systemd-analyze --user security).Seit ich Container auf Podman umstelle, nutze ich systemd häufiger, und dieses Tool wird sehr hilfreich sein, um die Sicherheit von systemd-Units bzw. Container-Services zu verbessern.
Früher waren Init-Skripte alle unterschiedlich, daher war so ein konsistentes Hardening nicht möglich.
Ich bin relativ spät zu Linux gekommen und kann mir Systeme ohne systemd kaum vorstellen; Systeme ohne systemd waren für mich viel zu umständlich.
Kürzlich habe ich das Tool
unshareentdeckt, mit dem ich etwa das gesamte/nixwieder als RW mounten und solche Experimente durchführen konnte, ohne andere Prozesse zu beeinflussen.systemd ist in der Bedienung zwar etwas kantig, aber ehrlich gesagt ist die einzige Alternative für mich Windows.
Ich frage mich, warum Linux-Distributionen nicht standardmäßig mehr solcher Sicherheitsschalter aktivieren.
Ich frage mich, ob konservatives Hardening irgendwelche Nachteile hat.
Für viele Nutzer könnten die Einstellungen einfach zu zahlreich und zu komplex sein.
Wenn man die Einstellungen zu aggressiv ändert, kann man unbeabsichtigt bestehende Konfigurationen kaputtmachen.
Wenn man zum Beispiel NetworkManager härten würde, müsste man einzeln prüfen, ob IPv4 und IPv6 beide funktionieren, ob die Modi
dns=systemd-resolvedunddns=defaultkorrekt arbeiten, wie es mit ModemManager und Mobilfunk-Integration aussieht, mit OpenVPN- oder Cisco-AnyConnect-Plugins, NetworkManager-dispatcher-Hooks und vielen weiteren Dingen.Außerdem ist die Frage, wie viele Paketbetreuer einer Distribution wirklich sicher sagen können, bis zu welchem Grad sie die Schalter eines von ihnen betreuten Pakets ändern können, ohne mehr als 0,01 % der Nutzerumgebungen zu beschädigen.
Wenn die Distribution solche Flags pflegt, kommen bei jedem Upstream-Release automatisch Kompatibilitätsprobleme dazu; wenn dagegen Upstream die Einstellungen setzt, kann man sie wegen der Abwärtskompatibilität nur noch vorsichtiger einsetzen.
Diese Frage ist ähnlich wie: „Warum setzen Distributionen nicht standardmäßig ein strengeres MAC wie SELinux ein?“
Auch
sshdkönnte man stärker einschränken, abermachen das für große Distributionen zu einer erheblichen Belastung.
Bei SELinux und AppArmor ist es ähnlich: Viele Maintainer halten das Kosten-Nutzen-Verhältnis für eher gering.
Ein weiterer wichtiger Grund ist, dass oft die Fähigkeit oder die Ressourcen fehlen, das korrekte Verhalten zentraler Systemdienste für jeden einzelnen Parameter per Integrationstests zu prüfen.
Relevante Diskussion:
https://news.ycombinator.com/item?id=29995566
Die Ergebnisse von
systemd-analyze securityunterscheiden sich je nach Distribution.desbma/shherzeugt aus mitstracegesammelten Daten automatisch regelbasierte Vorgaben wieSyscallFilter, ähnlich wieaudit2allowbei SELinux.Allerdings ist es diskussionswürdig,
stracein Produktionsumgebungen zu installieren.https://github.com/desbma/shh
Ich weiß es auch nicht genau, aber manche dieser Einstellungen sind erst neuer hinzugekommen, sodass viele Nutzer sie vielleicht noch gar nicht kennen.
Es gibt nicht nur systemd-Experten, und wenn man solche Optionen aktiviert, besteht auch das Risiko, dass ältere systemd-Versionen nicht mehr korrekt funktionieren.
Es gibt zwar viele Funktionen wie SELinux und AppArmor, aber viele Distributionen, Entwickler und Nutzer empfinden sie nicht unbedingt als notwendig, weshalb eine automatische Aktivierung schwierig ist.
Es gibt so viele Optionen fürs Hardening, dass ich denke, ein Repository mit allgemeinen Hardening-Beispielen für verschiedene Services wäre hilfreich.
Nutzer greifen oft auf gemeinsam verwendete Hardening-Skripte zurück, stellen dann aber überraschend fest, dass man Berechtigungen teils weiter fassen muss, damit es in Ausnahmesituationen nicht zu Problemen kommt.
nixpkgspaketiert,ist es am nützlichsten, sich anzusehen, wie Mainstream-Distributionen paketieren und härten.
Solche Hardening-Methoden sind oft schon ausreichend getestet; wenn man also Beispiele für Härtung etwa bei PostgreSQL sucht, startet man am besten mit den Paketen von Debian, Ubuntu oder RHEL.
Eine der großartigen Sicherheitsfunktionen von systemd ist das Credential-Management.
Damit lassen sich Zugangsdaten sicherer an Anwendungen übergeben, als wenn man sie in Umgebungsvariablen oder im Dateisystem speichert.
In Umgebungen ohne Vault und Ähnliches, zum Beispiel bei privaten Projekten, bevorzuge ich diese Methode immer.
Ich habe sogar selbst ein Go-Paket gebaut, das diese Funktion integriert.
Credentials in systemd
credential-go-Paket
Das wirkt wie bei nodejs oder npm, wo selbst zweizeiliger Code in ein Paket gepackt wird.
Tatsächlich ist es einfach
und nicht einmal komplizierter als
left-pad.Soweit ich weiß, galt es in der Go-Community eigentlich immer als Tugend, Abhängigkeiten zu reduzieren und unnötige Abstraktionen wie zusätzliche Funktionsaufrufe zu vermeiden.
Solche einfachen Dinge hat man früher meist direkt selbst geschrieben.
Ich frage mich, wie diese Methode der Credential-Übergabe verhindert, dass geforkte Kindprozesse die Zugangsdaten mit erben.
Wirklich ein sehr nützlicher Artikel.
Mir gefallen sowohl die Liste der einzelnen systemd-Optionen als auch Hinweise wie „Siehe man und viel Glück“.
systemd ist wirklich großartig, und ich würde es gern breit auf meinen Servern einsetzen.
Ein kleiner Hinweis: Die korrekte Schreibweise im Titel ist
systemd.Nicht
SystemD,system Dodersystem d, sondernsystemd.Der Grund ist, dass es für „system daemon“ steht und man gemäß der Unix-/Linux-Tradition einen Namen mit kleinem
dam Ende gewählt hat.Ich habe meistens
systemDgesehen und frage mich, warum sich das so weit verbreitet hat.Der Tipp zum Debuggen von Syscall-Problemen in systemd ist wirklich nützlich.