SELinux-cheat-sheet: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(Eine dazwischenliegende Version desselben Benutzers wird nicht angezeigt)
Zeile 93: Zeile 93:
  
 
{{Hinweis|
 
{{Hinweis|
Eine tückische Variante ist <code>/etc/ssl/own.*</code> (ohne Gruppierung). Das sieht aus wie Shell-Glob ("own, dann beliebiger Suffix"), ist aber reine Regex: der <code>.</code> matched ein beliebiges Zeichen, <code>*</code> wiederholt diesen Punkt beliebig oft. Trifft <code>own.crt</code> und <code>own.key</code> zufällig auch, aber aus einem anderen Grund als man beim Lesen vermutet – nämlich "own + ein-beliebiges-Zeichen + beliebig oft wiederholt", nicht "own + beliebiger Suffix". Sauberer wäre <code>/etc/ssl/own\.(crt|key)</code>.
+
Eine tückische Variante ist <code>/etc/ssl/own.*</code> (ohne Gruppierung). Das sieht aus wie Shell-Glob ("own, dann beliebiger Suffix"), ist aber reine Regex: der <code>.</code> matched ein beliebiges Zeichen, <code>*</code> wiederholt diesen Punkt beliebig oft. Trifft <code>own.crt</code> und <code>own.key</code> zufällig auch, aber aus einem anderen Grund als man beim Lesen vermutet – nämlich "own + ein-beliebiges-Zeichen + beliebig oft wiederholt", nicht "own + beliebiger Suffix". Sauberer wäre <nowiki>/etc/ssl/own\.(crt|key)</nowiki> .
 
}}
 
}}
  
Zeile 117: Zeile 117:
 
falls bereits vorhanden:
 
falls bereits vorhanden:
 
* semanage port -m -t http_port_t -p tcp 8080
 
* semanage port -m -t http_port_t -p tcp 8080
 
+
;Port aus einem Typ entfernen
 +
* semanage port -d -t http_port_t -p tcp 8080
 
{{Hinweis|
 
{{Hinweis|
 
Nur relevant, wenn ein Dienst auf einem '''Nicht-Standard-Port''' läuft (z. B. httpd auf 8080/8443 statt 80/443). Die Standardports sind bereits als <code>http_port_t</code> gelabelt – für einen gewöhnlichen Webserver auf 80/443 ist hier nichts zu tun.
 
Nur relevant, wenn ein Dienst auf einem '''Nicht-Standard-Port''' läuft (z. B. httpd auf 8080/8443 statt 80/443). Die Standardports sind bereits als <code>http_port_t</code> gelabelt – für einen gewöhnlichen Webserver auf 80/443 ist hier nichts zu tun.

Aktuelle Version vom 8. Juli 2026, 16:18 Uhr

Allgemeines

SELinux (Security-Enhanced Linux) implementiert Mandatory Access Control (MAC). Es isoliert Prozesse in Sicherheitskontexten, um das Schadenspotenzial bei Kompromittierungen zu minimieren.

Status und Modi prüfen

  • sestatus
  • getenforce

Modi temporär umschalten

Wechsel zu Permissive
  • setenforce 0
Wechsel zu Enforcing
  • setenforce 1

Modus dauerhaft setzen

Konfiguration in der Datei: /etc/selinux/config

  • SELINUX=enforcing
  • SELINUX=permissive

Dateikontexte verwalten

Kontexte anzeigen

zeigt alle Prozesse mit Kontexten

  • ps -eZ
  • ls -Z /pfad/zur/datei
Kontext temporär ändern

wird durch restorecon oder Relabel überschrieben

  • chcon -t httpd_sys_content_t /var/www/html/index.html
Kontext zurücksetzen auf Policy-Vorgabe

stellt den durch fcontext-Regeln definierten Kontext wieder her, unabhängig von manuellen chcon-Änderungen

  • restorecon -v /pfad/zur/datei
  • restorecon -Rv /pfad/zum/verzeichnis
Kontext dauerhaft definieren und anwenden

semanage trägt die Regel in die Policy-Datenbank ein, restorecon wendet sie auf bestehende Dateien an

  • semanage fcontext -a -t httpd_sys_content_t "/custom/www(/.*)?"
  • restorecon -Rv /custom/www
Vorhandene Kontext-Regeln nachschlagen

hilfreich um den passenden Typ für einen neuen Anwendungsfall zu finden, statt zu raten

  • semanage fcontext -l | grep httpd

Regex-Grundlagen bei semanage fcontext

⚠️ Achtung: semanage fcontext nutzt POSIX Extended Regex, keine Shell-Glob-Syntax. Das führt regelmäßig zu Verwechslungen, weil die Sonderzeichen anders funktionieren als man es aus der Shell (Bash-Globbing) gewohnt ist.

Shell-Glob Regex Bedeutung
* .* "beliebig viele Zeichen" – in Regex ist * allein nur "vorheriges Element beliebig oft wiederholen", kein eigenständiges Wildcard
? . "genau ein beliebiges Zeichen" – in Regex bedeutet ? "vorheriges Element optional", nicht "ein Zeichen"

Konkretes Beispiel aus der Praxis:

semanage fcontext -a -t httpd_sys_content_t "/var/repo(/.*)?"
Teil Bedeutung
/var/repo literaler, fester Text – muss genau so vorkommen
( ) Gruppierung – fasst den eingeschlossenen Ausdruck zusammen
/ literales Zeichen – ein fester Slash
. beliebiges einzelnes Zeichen (Wildcard)
* 0 bis unendlich Wiederholungen des davorstehenden Elements (hier: .)
.* zusammen: beliebig viele beliebige Zeichen (auch keins)
(/.*) Gruppe: ein / gefolgt von beliebig vielem Inhalt
? macht die davorstehende Gruppe optional (0 oder 1 mal)
(/.*)? die ganze Gruppe "/ + beliebiger Inhalt" ist optional

Matched:

  • /var/repo (Gruppe fehlt – erlaubt durch ?)
  • /var/repo/ (Gruppe = / + leerer Rest)
  • /var/repo/index.html
  • /var/repo/sub/dir/datei.txt (beliebige Tiefe)

Matched nicht:

  • /var/repository (kein / oder Ende direkt nach repo)
  • /var/repo2

ℹ️ Hinweis: Eine tückische Variante ist /etc/ssl/own.* (ohne Gruppierung). Das sieht aus wie Shell-Glob ("own, dann beliebiger Suffix"), ist aber reine Regex: der . matched ein beliebiges Zeichen, * wiederholt diesen Punkt beliebig oft. Trifft own.crt und own.key zufällig auch, aber aus einem anderen Grund als man beim Lesen vermutet – nämlich "own + ein-beliebiges-Zeichen + beliebig oft wiederholt", nicht "own + beliebiger Suffix". Sauberer wäre /etc/ssl/own\.(crt|key) .

Booleans verwenden

Booleans sind An/Aus-Schalter für ganze Verhaltensklassen einer SELinux-Policy, unabhängig von Datei-Labels. Sie werden nur gebraucht, wenn ein Dienst ein Verhalten zeigt, das die Standard-Policy für seinen Typ nicht automatisch erlaubt.

Alle Booleans anzeigen
  • getsebool -a
Spezifischen Wert prüfen
  • getsebool httpd_can_network_connect
Boolean dauerhaft aktivieren
  • setsebool -P httpd_can_network_connect on

ℹ️ Hinweis: Nicht jedes SELinux-Problem ist ein Boolean-Problem. Ein Webserver, der nur statischen Content ausliefert und PHP über einen lokalen Unix-Socket an PHP-FPM übergibt, braucht in der Regel keine zusätzlichen Booleans – httpd_can_network_connect ist z. B. nur relevant, wenn httpd selbst aktiv Netzwerkverbindungen aufbaut (Reverse-Proxy zu einem Backend, externe API-Calls etc.). Vor dem Setzen eines Booleans erst prüfen, ob das eigentliche Problem nicht schlicht ein fehlender oder falscher Dateikontext (fcontext) ist – das ist der weitaus häufigere Fall bei "Forbidden"-Fehlern auf eigenem Content.

Ports verwalten

Erlaubte Ports für einen Typ anzeigen
  • semanage port -l | grep http_port_t
Port zu einem Typ hinzufügen
  • semanage port -a -t http_port_t -p tcp 8080

falls bereits vorhanden:

  • semanage port -m -t http_port_t -p tcp 8080
Port aus einem Typ entfernen
  • semanage port -d -t http_port_t -p tcp 8080

ℹ️ Hinweis: Nur relevant, wenn ein Dienst auf einem Nicht-Standard-Port läuft (z. B. httpd auf 8080/8443 statt 80/443). Die Standardports sind bereits als http_port_t gelabelt – für einen gewöhnlichen Webserver auf 80/443 ist hier nichts zu tun.

Fehlersuche und Analyse

Vorhandene Policy-Regel prüfen

zeigt ob eine bestimmte Erlaubnis in der Policy überhaupt existiert, bevor man einen Boolean setzt oder ein Custom-Modul baut

  • sesearch --allow -s httpd_t -t var_t -c file
Logs nach aktuellen Blockaden (AVC) durchsuchen
  • ausearch -m avc -ts recent

größeres Zeitfenster, falls "recent" nichts findet:

  • ausearch -m avc -ts today
  • ausearch -m avc -ts boot

zeigt die Ursache der Blockade verständlich

  • ausearch -m avc -ts recent | audit2why
  • journalctl -t setroubleshoot
Analyse der Log-Einträge

Paket ggf. erforderlich: setroubleshoot-server

  • sealert -a /var/log/audit/audit.log
Eigene Policy-Module aus Logs erstellen

nur nach Prüfung verwenden – kann Sicherheitsregeln aufweichen

  • grep "denied" /var/log/audit/audit.log | audit2allow -M mycustommodule
  • semodule -i mycustommodule.pp

Praxisbeispiel: "Forbidden" trotz korrekter Apache-Config

Typischer Ablauf einer SELinux-bedingten 403-Fehlersuche, wie sie beim Einrichten eines eigenen DocumentRoot (z. B. /var/repo statt /var/www/html) auftritt:

  1. Apache-Config ist syntaktisch korrekt (apachectl configtest → Syntax OK), Dienst startet, Browser zeigt trotzdem "Forbidden".
  2. Prüfen: ausearch -m avc -ts recent – zeigt AVC-Denial mit tcontext=unconfined_u:object_r:var_t:s0 statt httpd_sys_content_t.
  3. Ursache: Der Pfad liegt außerhalb des von der Policy bereits abgedeckten /var/www/html und hat dadurch den generischen var_t-Kontext, den httpd nicht lesen darf.
  4. Fix: eigenen fcontext-Eintrag anlegen und anwenden.
semanage fcontext -a -t httpd_sys_content_t "/var/repo(/.*)?"
restorecon -Rv /var/repo
  1. Erneuter Test im Browser – Zugriff funktioniert.

ℹ️ Hinweis: /var/www/html ist von Haus aus bereits mit httpd_sys_content_t gelabelt. Sobald ein eigener Pfad außerhalb davon als DocumentRoot verwendet wird, ist ein eigener fcontext-Eintrag praktisch immer nötig – das ist kein Fehler in der Apache-Config, sondern erwartetes SELinux-Verhalten.

Best Practices

  • Betrieb im Modus 'enforcing' sicherstellen.
  • Modus 'permissive' nur zur Fehlersuche nutzen.
  • 'semanage fcontext' gegenüber 'chcon' bevorzugen (dauerhaft statt flüchtig).
  • Vor Erstellung eigener Module prüfen, ob ein passender Boolean existiert (getsebool -a).
  • Vor dem Setzen eines Booleans prüfen, ob nicht eigentlich ein fehlender fcontext-Eintrag die Ursache ist – bei "Forbidden" auf eigenem Content meist der Fall.
  • Bei fcontext-Regex-Mustern beachten: POSIX Extended Regex, keine Shell-Glob-Syntax (.* statt *, . statt ?).
  • Relabeling des Dateisystems bei Bedarf: touch /.autorelabel