Aus Linux-Magazin 11/2021

Dienste mithilfe von Systemd absichern

© Augustas Cetkauskas / 123RF.com

Wie sicher ist sicher? Systemd bringt dafür ein Messinstrument mit. Wer es nutzt, kann mitverfolgen, wie sich ein beliebiger Dienst Schritt für Schritt in einer Sandbox absichern lässt.

Eines der wichtigen Ziele bei der Systemd-Entwicklung ist ein sicheres Linux. Nun kann man nur verbessern, was sich messen lässt, weshalb schon der alte Grieche Archimedes von Syrakus riet: “Miss alles, was sich messen lässt, und mach alles messbar, was sich nicht messen lässt.” Dieser Maxime folgend macht Systemd nun die Systemsicherheit unter Linux mess- und verbesserbar.

Konkret ist es das Kommando »systemd-analyze« mit dem Parameter »security«, das das bewerkstelligt. Führt man es aus, liefert es eine Tabelle wie in Abbildung 1: Sie führt jeden von Systemd verwalteten Service auf (UNIT), dazu einen Zahlenwert für den Schutzgrad (EXPOSURE, wobei 10 der höchste und zugleich schlechteste Wert ist), eine verbale Übersetzung dieses Werts (PREDICATE) und schließlich noch eine dritte Darstellung der Bewertung in Form eines Emojis.

Abbildung 1: Die tabellarische Bewertung aller Services nach Sicherheitsgesichtspunkten.

Abbildung 1: Die tabellarische Bewertung aller Services nach Sicherheitsgesichtspunkten.

Zusätzlich kann Systemd-analyze preisgeben, wie es zu seiner Einschätzung kommt: Dafür starten Sie es mit dem Namen einer konkreten Service-Unit. Nun listet es wie in Abbildung 2 alle überprüften Faktoren nebst Markierung für die Erfüllung (Haken) oder Nichterfüllung (Kreuz).

Abbildung 2: Die Detaildarstellung aller Faktoren, die in die Bewertung eingingen.

Abbildung 2: Die Detaildarstellung aller Faktoren, die in die Bewertung eingingen.

Härtefall

Danach kennt der Nutzer also die Meinung von Systemd zur Sicherheitslage der geprüften Dienste – aber was lässt sich tun, um sie zu verbessern? Um das herauszufinden, basteln Sie sich einen minimalen Service, dessen Sicherheit Sie dann Schritt für Schritt anheben. Dazu legen Sie zunächst in einem leeren Verzeichnis (im Beispiel »/home/$USER/Python/sectest/«, das später als Document Root eines kleinen Webservers dienen soll, eine minimalistische HTML-Seite an (Listing 1).

Listing 1

Minimale HTML-Seite

<!doctype html>
<html lang=en>
  <head>
    <meta charset=utf-8>
    <title>Hello World</title>
  </head>
  <body>
    <p><h1>HELLO WORLD!</h1></p>
  </body>
</html>

Den Webserver selbst borgen Sie sich am einfachsten bei Python aus, denn das bringt bereits ein schlichtes Modell mit, das sich so gut wie ohne Konfiguration verwenden lässt. Den Server-Start verpacken Sie in ein Systemd-Unit-File, das wiederum so einfach wie möglich ausfällt (Listing 2). Das Unit-File landet als »helloworld.service« im Verzeichnis »/lib/systemd/system«, die HTML-Seite als »index.html« im besagten Document-Root-Verzeichnis. Nach einem »systemctl start helloworld.service« sollte die Eingabe von »localhost:8080« in der Adresszeile eines Webbrowsers die schlichte Hello-World-Seite auf den Bildschirm bringen.

Listing 2

Unit-File

[Unit]
Description=Simple Http Server
Documentation=https://docs.python.org/3/library/http.server.html
[Service]
Type=simple
WorkingDirectory=/home/jcb/Python/sectest
ExecStart=/usr/bin/python3 -m http.server 8080
ExecStop=/bin/kill -9 $MAINPID
[Install]
WantedBy=multi-user.target

In diesem Zustand, ohne irgendwelche Vorkehrungen, ist der Service noch vollkommen ungeschützt. In der Ausgabe von »systemd-analyze security« erscheint er mit der hohen Punktzahl 9,6 als UNSAFE mit entsetztem Emoji (Abbildung 3).

Abbildung 3: Ausgangspunkt: Der neue Service ist noch vollkommen unsicher.

Abbildung 3: Ausgangspunkt: Der neue Service ist noch vollkommen unsicher.

Grundlegendes

Im ersten Schritt ergänzen Sie im Service-Abschnitt des Unit-Files die Zeile »NoNewPrivileges=true«. Das verhindert, dass der Prozess später mehr Privilegien erlangen kann, als ihm ursprünglich zugewiesen wurden, zum Beispiel mithilfe von »setuid«- oder »setgid«-Bits. Danach (wie auch bei allen folgenden Ergänzungen des Unit-Files) fällt ein »systemctl daemon-reload« an, gefolgt von einem »systemctl restart helloworld.service«. Betrachten Sie jetzt die Ausgabe von »systemd-analyze security«, ist der Exposure-Wert von »helloworld.service« schon leicht gesunken, von 9,6 auf 9,4. Als UNSAFE gilt er freilich immer noch.

Also weiter im Text: Eine ganze Klasse von Angriffen lässt sich unmöglich machen, indem Sie nun im Unit-File »PrivateTmp=yes« ergänzen. Das bewirkt, dass Systemd für den Prozess einen neuen, exklusiven Filesystem-Namensraum erzeugt und »/tmp« sowie »/var/tmp/« dorthin mountet. So werden temporäre Files nicht mehr öffentlich geteilt und nach dem Ende des Prozesses sofort gelöscht. Angriffe, die auf dem Austausch oder der Manipulation temporärer Dateien beruhen, laufen so ins Leere. Der Exposure-Wert sinkt auf 9.0, die Bewertung bleibt aber auf UNSAFE.

Es gibt also noch einiges zu tun. Im nächsten Schritt ergänzen Sie das Unit-File mit dem Eintrag »RestrictNamespaces=uts ipc pid user cgroup«. Das unterbindet für den Prozess den Zugriff auf die aufgeführten Namespaces. Die Aufzählung lässt unter anderem den Namespace »net« aus, den der Webserver naturgemäß verwenden muss. Mit dieser Maßnahme sinkt der Exposure Wert erstmals unter 9 (auf 8,8), und die Bewertung lautet nicht mehr UNSAFE, sondern nur noch EXPOSED. Das Emoji wechselt von einem entsetzten zu einem nur noch unzufriedenen Ausdruck.

Kernel und Control Groups

Im nächsten Schritt stellen Sie im Unit-File die zusätzlichen Schutzmechanismen »ProtectKernelTunables=yes«, »ProtectKernelModules=yes« und »ProtectControlGroups=yes« ein. Das macht die Kernel-Variablen, auf die der Anwender via »/proc/sys/«, »/sys«, »/proc/sysrq-trigger/«, »/proc/latency_stats/«, »/proc/acpi/«, »/proc/timer_stats/«, »/proc/fs/« und »/proc/irq/« zugreifen kann, für den Prozess read-only und damit nicht mehr veränderbar. Ohnehin sollte das System auf diese Variablen nur während des Bootens schreibend zugreifen, Sie büßen dadurch also keine Funktionalität ein. Da unser Webserver keine speziellen Kernel-Module braucht, haben Sie ihm auch das Laden und Entladen solcher Module für den Webserver-Prozess verboten. Genauso untersagt ist ihm ab sofort der Zugriff auf die Control Groups, den höchstens Container-Verwaltungssoftware benötigt, nicht aber ein Webserver. Das drückt den Exposure-Wert auf jetzt 8,1.

Schließlich können Sie noch »ProtectSystem=strict« einstellen. Das mountet »/usr« und die Bootloader-Verzeichnisse »/boot« sowie »/efi« für alle Prozesse, die diese Unit startet, im Read-only-Modus. Zusätzlich legen Sie »PrivateUsers=strict« fest. Diese Einstellung konfiguriert für den Prozess ein User-Group-Mapping, das Root und den User, der den Hauptprozess der Unit startet, auf sich selbst abbildet, aber alle anderen Benutzer oder Gruppen auf nobody mappt. Die User- und Gruppen-Datenbank des Systems wird so vom Prozess entkoppelt, der in seiner eigenen Sandbox läuft. Der Exposure-Wert sinkt damit unter 8 (genauer: auf 7,8).

Capabilities

Zum Schluss beschränken Sie noch die Capabilities, die dem Prozess zur Verfügung stehen sollen. Dabei handelt es sich um Rechte, die man unprivilegierten Prozessen quasi häppchenweise zugestehen kann. Das macht es überflüssig, einem Prozess die vollkommen unbeschränkten Superuser-Rechte übertragen zu müssen, nur weil er ein einzelnes Sonderrecht benötigt.

Wir gehen hier recht restriktiv vor und definieren »CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_DAC_READ_SEARCH«. Damit schließt beispielsweise die Zuweisung von »CAP_SYS_ADMIN«, »CAP_DAC_OVERRIDE« oder »CAP_SYS_PTRACE« an den Prozess aus und bringt viele Punkte. Der Exposure-Wert fällt damit auf 5,7 (Abbildung 4): Die Bewertung bescheinigt uns nun ein mittleres Sicherheitsniveau, und das Emoji schaut zum ersten Mal neutral und nicht mehr grimmig in die Welt.

Abbildung 4: Zum ersten Mal ist das Emoji nicht unzufrieden: Sie haben ein mittleres Sicherheitsniveau erreicht.

Abbildung 4: Zum ersten Mal ist das Emoji nicht unzufrieden: Sie haben ein mittleres Sicherheitsniveau erreicht.

Fazit

Es bleiben noch etliche Möglichkeiten, um für zusätzliche Sicherheit zu sorgen. Eine gute Zusammenstellung aller Systemd-Optionen, die sich für das Härten von Diensten eignen, liefert beispielsweise eine Beschreibung auf Github [1]. Sie eröffnen ein weites Feld für weitere Optimierungen. Mit Systemd-analyze als Messinstrument können Sie Ihre Fortschritte dabei jeweils mitverfolgen. (jcb/jlu)

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 3 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben