SELinux-Konzepte

Machen Sie sich auf dieser Seite mit den SELinux-Konzepten vertraut.

Mandatorische Zugriffssteuerung

Security-Enhanced Linux (SELinux) ist ein System zur obligatorischen Zugriffssteuerung (Mandatory Access Control, MAC) für das Linux-Betriebssystem. Als MAC-System unterscheidet es sich vom bekannten DAC-System (Discretionary Access Control, benutzerbestimmbare Zugriffssteuerung) von Linux. In einem DAC-System gibt es das Konzept des Eigentums, bei dem ein Eigentümer einer bestimmten Ressource die damit verbundenen Zugriffsberechtigungen steuert. Dies ist in der Regel grob und unterliegt einer unbeabsichtigten Rechteausweitung. Ein MAC-System fragt jedoch bei allen Zugriffsversuchen eine zentrale Stelle um eine Entscheidung.

SELinux wurde als Teil des Linux Security Module (LSM)-Frameworks implementiert, das verschiedene Kernel-Objekte und sensible Aktionen erkennt, die an 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 in einem undurchsichtigen Sicherheitsobjekt gespeicherten Informationen zu bestimmen, ob die Aktion zulässig sein soll. SELinux bietet eine Implementierung für diese Hooks und die Verwaltung dieser Sicherheitsobjekte, die in Kombination mit der eigenen Richtlinie die Zugriffsentscheidungen bestimmen.

Zusammen mit anderen Android-Sicherheitsmaßnahmen schränkt die Android-Zugriffssteuerungsrichtlinie den potenziellen Schaden kompromittierter Geräte und Konten erheblich ein. Mit Tools wie den optionalen und obligatorischen Zugriffskontrollen von Android können Sie dafür sorgen, dass Ihre Software nur mit der Mindestberechtigungsstufe ausgeführt wird. So werden die Auswirkungen von Angriffen gemindert und die Wahrscheinlichkeit verringert, dass fehlerhafte Prozesse Daten überschreiben oder sogar übertragen.

In Android 4.3 und höher bietet SELinux eine obligatorische Zugriffskontrolle (Mandatory Access Control, MAC) für Umgebungen mit traditioneller Zugriffskontrolle (Discretionary Access Control, DAC). Software muss beispielsweise in der Regel als Root-Nutzerkonto ausgeführt werden, um auf Rohblockgeräte schreiben zu können. In einer herkömmlichen DAC-basierten Linux-Umgebung kann der Root-Nutzer, wenn er kompromittiert wird, auf jedes Raw-Blockgerät schreiben. SELinux kann jedoch verwendet werden, um diese Geräte zu kennzeichnen, sodass der Prozess, dem das Root-Privileg zugewiesen ist, nur in die in der zugehörigen Richtlinie angegebenen Geräte schreiben kann. So können durch den Prozess keine Daten und Systemeinstellungen außerhalb des spezifischen Raw-Blockgeräts ü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:

  • Erlaubt: Die SELinux-Sicherheitsrichtlinie wird nicht erzwungen, sondern nur protokolliert.
  • Erzwingen: 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 ob Sie nur potenzielle Fehler erfassen können. „Permissive“ ist besonders bei der Implementierung nützlich.

Typen, Attribute und Regeln

Android verwendet die Type Enforcement (TE)-Komponente von SELinux für seine Richtlinie. Das bedeutet, dass alle Objekte (z. B. Datei, Prozess oder Socket) einen Typ haben. Standardmäßig hat eine App beispielsweise den Typ untrusted_app. Der Typ eines Prozesses wird auch als Domain bezeichnet. Ein Typ kann mit einem oder mehreren Attributen annotiert werden. Attribute sind nützlich, um gleichzeitig auf mehrere Typen zu verweisen.

Objekte werden Klassen zugeordnet (z. B. einer Datei, einem Verzeichnis, einem symbolischen Link oder einem Socket). Die verschiedenen Arten des Zugriffs für jede Klasse werden durch Berechtigungen dargestellt. Für die Klasse file gibt es beispielsweise die Berechtigung open. Während Typen und Attribute regelmäßig im Rahmen der Android-SELinux-Richtlinie aktualisiert werden, sind Berechtigungen und Klassen statisch definiert und werden selten im Rahmen einer neuen Linux-Version aktualisiert.

Eine Regel für eine Richtlinie hat das folgende Format: allow source target:class permissions; Dabei gilt:

  • Quelle: Der Typ (oder das Attribut) des Subjekts der Regel. Wer fordert den Zugriff an?
  • Ziel: Der Typ (oder das Attribut) des Objekts. Wofür wird der Zugriff angefordert?
  • Klasse: Die Art des Objekts (z. B. Datei, Socket), auf das zugegriffen wird.
  • Berechtigungen: Der Vorgang (oder die Gruppe von Vorgängen), der ausgeführt wird (z. B. Lesen, Schreiben).

Ein Beispiel für eine Regel:

allow untrusted_app app_data_file:file { read write };

Das bedeutet, dass Apps Dateien mit dem Label app_data_file lesen und schreiben dürfen. Es gibt auch andere Arten von Apps. Für Instanzen 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 in einer Regel ein Attributname angegeben wird, wird dieser Name automatisch auf die Liste der Domains oder Typen erweitert, die dem Attribut zugeordnet sind. Einige wichtige Attribute:

  • domain – Attribut, das allen Prozesstypen zugeordnet ist.
  • file_type: Attribut, das allen Dateitypen zugeordnet ist.

Makros

Insbesondere für den Dateizugriff gibt es viele Arten von Berechtigungen, die berücksichtigt werden müssen. Die Berechtigung read reicht beispielsweise nicht aus, um die Datei zu öffnen oder stat für sie aufzurufen. Um die Regeldefinition zu vereinfachen, bietet Android eine Reihe von Makros für die häufigsten Fälle. Um beispielsweise die fehlenden Berechtigungen wie open einzuschließen, könnte die obige Regel so umgeschrieben 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 für zugehörige Berechtigungen zu verringern.

Sobald ein Typ definiert ist, muss er der Datei oder dem Prozess zugeordnet werden, die bzw. den er repräsentiert. Weitere Informationen dazu, wie diese Zuordnung erfolgt, finden Sie unter SELinux implementieren. Weitere Informationen zu Regeln finden Sie im SELinux-Notebook.

Sicherheitskontext und ‑kategorien

Beim Debuggen von SELinux-Richtlinien oder beim Kennzeichnen von Dateien (mit file_contexts oder ls -Z) stoßen Sie möglicherweise auf einen Sicherheitskontext (auch als Label bezeichnet). 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 in der Regel ignoriert werden (siehe Spezifität). Das Feld type wird im vorherigen Abschnitt erläutert. categories sind Teil der MLS-Unterstützung (Multi-Level Security) in SELinux. In Android 12 und höher werden Kategorien für Folgendes verwendet:

  • App-Daten vor dem Zugriff durch eine andere App schützen
  • App-Daten von einem physischen Nutzer zu 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. Es gibt einige Ausnahmen für die Verwendung von Common Intermediate Language (CIL).
  • SELinux-Nutzer werden nicht verwendet. Der einzige benutzerdefinierte Nutzer ist u. Bei Bedarf werden physische Nutzer über das Feld „Kategorien“ eines Sicherheitskontexts dargestellt.
  • SELinux-Rollen und die rollenbasierte Zugriffssteuerung (Role-Based Access Control, RBAC) werden nicht verwendet. Es werden zwei Standardrollen definiert und verwendet: r für Subjekte und object_r für Objekte.
  • SELinux-Vertraulichkeitsstufen werden nicht verwendet. Die Standardempfindlichkeit für 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 Überprüfung und das Debugging von Richtlinien.