SELinux-Konzepte

Auf dieser Seite finden Sie Informationen zu den SELinux-Konzepten.

Mandatory Access Control

Security Enhanced Linux (SELinux) ist ein MAC-System (Mandatory Access Control) für das Linux-Betriebssystem. Als MAC-System unterscheidet es sich vom bekannten DAC-System (Discretionary Access Control) von Linux. In einem DAC-System gibt es ein Konzept der Inhaberschaft, bei dem der Inhaber einer bestimmten Ressource die zugehörigen Zugriffsberechtigungen verwaltet. Dieser Ansatz ist in der Regel grob und kann zu unbeabsichtigten Berechtigungseskalationen führen. Ein MAC-System konsultiert jedoch eine zentrale Autorität für eine Entscheidung bei allen Zugriffsversuchen.

SELinux wurde als Teil des Linux Security Module (LSM)-Frameworks implementiert, das verschiedene Kernelobjekte und sensible Aktionen erkennt, die auf ihnen ausgeführt werden. An dem Punkt, an dem jede dieser Aktionen ausgeführt werden würde, wird eine LSM-Hook-Funktion aufgerufen, um anhand der Informationen, die in einem undurchsichtigen Sicherheitsobjekt gespeichert sind, zu bestimmen, ob die Aktion zulässig ist oder nicht. SELinux bietet eine Implementierung für diese Hooks und die Verwaltung dieser Sicherheitsobjekte, die mit den eigenen Richtlinien kombiniert werden, um die Zugriffsentscheidungen zu treffen.

Zusammen mit anderen Android-Sicherheitsmaßnahmen begrenzt die Zugriffssteuerung von Android den potenziellen Schaden durch manipulierte Computer und Konten erheblich. Mit Tools wie den bedarfsgesteuerten und obligatorischen Zugriffssteuerungen von Android können Sie dafür sorgen, dass Ihre Software nur mit den minimalen Berechtigungen ausgeführt wird. So werden die Auswirkungen von Angriffen abgemildert und die Wahrscheinlichkeit verringert, dass fehlerhafte Prozesse Daten überschreiben oder sogar übertragen.

In Android 4.3 und höher bietet SELinux eine Mandatory Access Control (MAC) für traditionelle Umgebungen mit bedarfsgesteuerter Zugriffssteuerung (Discretionary Access Control, DAC). Beispielsweise muss Software in der Regel als Root-Nutzerkonto ausgeführt werden, um auf Raw-Blockgeräte zu schreiben. Wenn in einer traditionellen DAC-basierten Linux-Umgebung der Root-Nutzer manipuliert wird, kann dieser Nutzer auf jedes Raw-Blockgerät schreiben. Mit SELinux können diese Geräte jedoch so gekennzeichnet werden, dass der Prozess, dem das Root-Berechtigung zugewiesen ist, nur auf die in der zugehörigen Richtlinie angegebenen Dateien schreiben kann. So können Daten und Systemeinstellungen außerhalb des jeweiligen Raw-Blockgeräts nicht überschrieben werden.

Weitere Beispiele für Bedrohungen und Möglichkeiten, diese mit SELinux zu beheben, finden Sie unter Anwendungsfälle.

Maßnahmenebenen

SELinux kann in verschiedenen Modi implementiert werden:

  • Permissive: Die SELinux-Sicherheitsrichtlinie wird nicht erzwungen, sondern nur protokolliert.
  • Erzwungen: Die Sicherheitsrichtlinie wird erzwungen und protokolliert. Fehler werden als EPERM-Fehler angezeigt.

Diese Auswahl ist binär und bestimmt, ob Ihre Richtlinie Maßnahmen ergreift oder Sie lediglich die Möglichkeit bietet, potenzielle Fehler zu erfassen. Die permissive Zugriffssteuerung ist besonders während der Implementierung nützlich.

Typen, Attribute und Regeln

Android verwendet für seine Richtlinie die TE-Komponente (Type Enforcement) von SELinux. Das bedeutet, dass allen Objekten (z. B. Dateien, Prozessen oder Sockets) ein Typ zugewiesen ist. Eine App hat beispielsweise standardmäßig den Typ untrusted_app. Der Typ eines Prozesses wird auch als Domain bezeichnet. Ein Typ kann mit einem oder mehreren Attributen versehen werden. Attribute sind nützlich, um gleichzeitig auf mehrere Typen zu verweisen.

Objekte werden Klassen zugeordnet (z. B. eine Datei, ein Verzeichnis, ein symbolischer Link oder ein Socket). Die verschiedenen Zugriffsarten für jede Klasse werden durch Berechtigungen dargestellt. Beispiel: Die Berechtigung open existiert für die Klasse file. Während Typen und Attribute im Rahmen der Android-SELinux-Richtlinie regelmäßig aktualisiert werden, sind Berechtigungen und Klassen statisch definiert und werden nur selten im Rahmen einer neuen Linux-Version aktualisiert.

Eine Richtlinienregel hat das folgende Format: allow source target:class permissions; wobei:

  • Quelle: Der Typ (oder das Attribut) des Betreffs der Regel. Wer fordert den Zugriff an?
  • Ziel: Der Typ (oder das Attribut) des Objekts. Worauf wird der Zugriff angefordert?
  • Class: Die Art des Objekts, auf das zugegriffen wird (z. B. Datei, Socket).
  • Berechtigungen: Der Vorgang (oder die Vorgänge) (z. B. Lesen, Schreiben), der ausgeführt wird.

Hier ein Beispiel für eine Regel:

allow untrusted_app app_data_file:file { read write };

Das bedeutet, dass Apps Dateien mit der Kennzeichnung app_data_file lesen und schreiben dürfen. Es gibt noch weitere Typen für Apps. Beispielsweise wird isolated_app für App-Dienste mit isolatedProcess=true im Manifest verwendet. Anstatt die Regel für beide Typen zu wiederholen, verwendet Android für alle Typen, die Apps abdecken, ein Attribut namens appdomain:

# Associate the attribute appdomain with the type untrusted_app.
typeattribute untrusted_app appdomain;

# Associate the attribute appdomain with the type isolated_app.
typeattribute isolated_app appdomain;

allow appdomain app_data_file:file { read write };

Wenn eine Regel geschrieben wird, in der ein Attributname angegeben ist, wird dieser Name automatisch auf die Liste der mit dem Attribut verknüpften Domains oder Typen erweitert. Zu den wichtigsten Attributen gehören:

  • domain – Attribut, das mit allen Prozesstypen verknüpft ist,
  • file_type: Attribut, das allen Dateitypen zugeordnet ist.

Makros

Insbesondere für den Dateizugriff gibt es viele Arten von Berechtigungen. Die Berechtigung read reicht beispielsweise nicht aus, um die Datei zu öffnen oder stat darauf anzuwenden. Zur Vereinfachung der Regeldefinition bietet Android eine Reihe von Makros für die häufigsten Fälle. Wenn Sie beispielsweise die fehlenden Berechtigungen wie open einschließen möchten, könnte die obige Regel so umformuliert werden:

allow appdomain app_data_file:file rw_file_perms;

Weitere Beispiele für nützliche Makros finden Sie in den Dateien global_macros und te_macros. Makros sollten nach Möglichkeit verwendet werden, um die Wahrscheinlichkeit von Fehlern aufgrund von Ablehnungen zugehörigen Berechtigungen zu verringern.

Nachdem ein Typ definiert wurde, muss er der Datei oder dem Prozess zugeordnet werden, den er darstellt. Weitere Informationen dazu, wie diese Verknüpfung hergestellt wird, finden Sie unter SELinux implementieren. Weitere Informationen zu Regeln finden Sie im SELinux-Notebook.

Sicherheitskontext und -kategorien

Wenn Sie SELinux-Richtlinien debuggen oder Dateien mit file_contexts oder ls -Z labeln, stoßen Sie möglicherweise auf einen Sicherheitskontext (auch Label genannt). Beispiel: u:r:untrusted_app:s0:c15,c256,c513,c768. Ein Sicherheitskontext hat das Format user:role:type:sensitivity[:categories]. Die Felder user, role und sensitivity eines Kontexts können Sie in der Regel ignorieren (siehe Spezifizität). Das Feld type wurde im vorherigen Abschnitt erläutert. categories sind Teil der Multi-Level Security (MLS)-Unterstützung in SELinux. Unter Android 12 und höher werden Kategorien für Folgendes verwendet:

  • App-Daten vor dem Zugriff durch andere Apps schützen,
  • App-Daten von einem Nutzer von einem anderen isolieren.

Spezifität

Android nutzt nicht alle Funktionen von SELinux. Beachten Sie beim Lesen externer Dokumentation Folgendes:

  • Die meisten Richtlinien in AOSP werden mit der Kernel Policy Language definiert. Für die Verwendung von Common Intermediate Language (CIL) gibt es einige Ausnahmen.
  • SELinux-Nutzer werden nicht verwendet. Die einzige benutzerdefinierte Taste ist u. Bei Bedarf werden physische Nutzer über das Feld „categories“ eines Sicherheitskontexts dargestellt.
  • SELinux-Rollen und die rollenbasierte Zugriffssteuerung (Role-Based Access Control, RBAC) werden nicht verwendet. Es sind zwei Standardrollen definiert und werden verwendet: r für Subjekte und object_r für Objekte.
  • Die SELinux-Sensitivitäten werden nicht verwendet. Die Standardempfindlichkeit von s0 ist immer festgelegt.
  • SELinux-Boolesche-Werte werden nicht verwendet. Wenn die Richtlinie für ein Gerät erstellt wird, hängt sie nicht vom Status des Geräts ab. Dies vereinfacht die Prüfung und Fehlerbehebung bei Richtlinien.