# 1.104.5

# Zugriffskontrolle auf Dateien mittels Zugriffsrechten

Beschreibung: Prüfungskandidaten sollten in der Lage sein, Dateizugriff mittels Zugriffsberechtigungen zu steuern. Dieses Lernziel beinhaltet Zugriffsrechte auf reguläre und spezielle Dateien sowie Verzeichnisse. Ebenfalls enthalten sind Zugriffsmodi wie suid, sgid und sticky bit, die Verwendung des Gruppenfeldes für die Vergabe von Zugriffsrechten an Arbeitsgruppen, das immutable flag und der voreingestellte Dateierstellungsmodus.

Die wichtigsten Dateien, Bezeichnungen und Anwendungen:

- chmod
- umask
- chattr

Die Zugriffsrechte unter Linux/Unix sind im Prinzip sehr einfach aufgebaut, jedoch aber auch sehr wirkungsvoll, wenn man weiß, wie sie im Einzelnen angewandt werden. Das Wissen um diese Rechte ist absolutes Grundwissen für alle, die mit Systemverwaltung unter Linux beschäftigt sind und sollte daher im Schlaf beherrscht werden.

### Grundsätzlicher Aufbau von Zugriffsrechten

Jede Datei in einem Linux-System - also auch Gerätedateien, Sockets, Pipes, Verzeichnisse, usw. - besitzt in ihrer Inode eine Angabe über die Zugriffsrechte. Außerdem hat jede Datei genau einen Eigentümer und genau eine Gruppe, der sie zugehört. Die Zugriffsrechte beziehen sich immer auf eben diesen Eigentümer der Datei, auf Gruppenmitglieder der Gruppe, der die Datei angehört und auf den Rest der Welt.

Für diese drei Kategorien (Eigentümer, Gruppe, Rest) existiert jeweils eine Angabe, die beschreibt, ob die Datei für die jeweilige Kategorie lesbar (r), beschreibbar (w) und ausführbar (x) ist.

Der Befehl `ls -l` Dateiname zeigt uns für jede Datei eben diese Angaben. So bedeutet die Ausgabe:

    -rw-r-----   1 hans     autoren         1519 Jul 29  2000 Testdatei

Die Datei Testdatei ist eine reguläre Datei (-). Sie gehört dem User hans, der sie lesen und verändern darf (rw-). Die Datei gehört zur Gruppe autoren. Mitglieder dieser Gruppe dürfen die Datei lesen (r--). Der Rest der Welt hat keinerlei Rechte auf diese Datei (---).

Das erste Zeichen der Ausgabe zeigt uns also, um was für eine Art Datei es sich handelt. Folgende Dateiarten sind unter Linux definiert:

Zeichen | Dateiart
--- | ---
`-` | Reguläre (normale) Datei
`d` | Verzeichnis (directory)
`l` | Symbolischer Link (symlink)
`b` | Blockorientierte Gerätedatei (block device)
`c` | Zeichenorientierte Gerätedatei (character device)
`p` | Feste Programmverbindung (named pipe)
`s` | Netzwerk Kommunikationsendpunkt (socket)

Das dem ersten Zeichen folgende Konstrukt ist die Beschreibung des Zugriffsmodus. Die ersten drei Zeichen beschreiben die Rechte des Eigentümers der Datei, die nächsten drei die Rechte eines Gruppenmitglieds der Gruppe, der auch die Datei zugehört und die letzten drei die Rechte aller anderen User. Ein `r` bedeutet Leserecht (read), ein `w` Schreibrecht (write) und ein `x` Ausführungsrecht (execute). Diese Rechte können numerisch dargestellt werden. Dazu werden die Rechte wie folgt bezeichnet:

Eigentümer | Gruppenmitglied | Rest der Welt
--- | --- | ---
`r` | `w` | `x` | `r` | `w` | `x` | `r` | `w` | `x`
`4` | `2` | `1` | `4` | `2` | `1` | `4` | `2` | `1`

Die Nummern werden für jede der drei Kategorien einzeln addiert. Ein Zugriffsrecht von `rw-r-----` wäre so also numerisch darstellbar als 640. Die 6 errechnet sich aus dem r (4) plus w (2) des Eigentümerrechtes, die 4 ist einfach das Leserecht (r) des Gruppenmitglieds und die 0 entspricht keinem gesetzten Recht.

Für reguläre Dateien sind diese Rechte einfach zu durchschauen. Das Leserecht bedeutet, daß der Inhalt der Datei gelesen werden darf. Das Schreibrecht bedeutet, daß der Inhalt der Datei verändert werden darf (und somit die Datei auch gelöscht werden darf) und das Ausführungsrecht bedeutet, daß die Datei ein Programm ist, das ausgeführt werden darf.

Etwas anders sieht es mit Verzeichnissen aus. Hier bedeutet das Leserecht, daß der Inhalt eines Verzeichnisses aufgelistet werden darf, das Schreibrecht, daß Dateien im Verzeichnis angelegt und gelöscht werden dürfen und das Ausführungsrecht, daß in das Verzeichnis gewechselt werden darf. Das hat einen Haken, zu dem wir später noch kommen werden. Hat nämlich ein User Schreibrecht auf ein Verzeichnis, so darf er darin auch Dateien löschen, auf die er selbst keinerlei Rechte besitzt. Das liegt an der Tatsache, daß ein Verzeichnis genau genommen nur eine Datei ist, die Dateinamen und die dazu passenden Inode-Nummern gespeichert hat. Eine Datei in einem Verzeichnis ist also letztlich nichts anderes als eine Zeile Text in einer Textdatei. Und wer Schreibrechte auf eine Textdatei hat, kann Zeilen daraus löschen!

### Spezielle Rechte

Neben diesen sichtbaren Rechten existieren noch drei weitere, die man sich als weitere (führende) Nummer vorstellen kann. Dabei handelt es sich um das Substitute UserID Bit (4), das Substitute GroupID Bit (2) und das Sticky Bit (1).

Substitute UserID Bit (SUID)
  Dieses Recht gilt ausschließlich für ausführbare Dateien. Hat eine ausführbare Datei dieses Recht gesetzt, so erscheint in der Darstellung durch das ls -l Kommando statt dem x beim Eigentümerrecht ein s. Jeder User, der dieses Programm ausführt, tut dies unter der effektiven UserID des Users, dem die Datei gehört.

  So hat z.B. das Programm /usr/bin/passwd die Aufgabe, daß auch normale User damit ihr eigenes Passwort ändern können. Dieses Passwort wird aber gespeichert in einer Datei, die nur von root beschrieben werden darf. Das Programm /usr/bin/passwd hat als Eigentümer root und hat das Substitute UserID Bit gesetzt. Jeder User, der dieses Programm ausführt tut dies also unter der effektiven UserID von root und hat daher die Rechte von root während der Ausführung. Das ermöglicht es dem Programm, das veränderte Passwort zu speichern.

  Das ist beim Passwort-Programm nicht weiter problematisch, eine richtige Sicherheitslücke entsteht, wenn eine Shell mit diesem Bit ausgestattet ist und als Eigentümer root hat. Dann könnte jeder User, der diese Shell ausführt, root-Rechte benutzen!

Substitute GroupID Bit (SGID)
  Dieses Recht gilt einerseits für ausführbare Dateien und andererseits für Verzeichnisse. Hat ein ausführbares Programm dieses Recht gesetzt, so gilt der gleiche Mechanismus, wie beim Substitute UserID Bit, nur diesmal eben die Gruppenmitgliedschaft betreffend. Ein User, der dieses Programm ausführt, tut dies als Gruppenmitglied der Gruppe, der das Programm gehört, statt seiner eigentlichen Gruppenkennung. Er hat also die Rechte eines Gruppenmitglieds dieser Gruppe, auch wenn er selbst nicht Mitglied dieser Gruppe ist. Statt dem x beim Gruppenrecht stellt das ls -l Kommando hier ein s dar.

  Hat ein Verzeichnis dieses Recht gesetzt, dann liegt der Fall etwas anders. Legt ein User, der Schreibrecht auf ein Verzeichnis hat, in diesem Verzeichnis eine Datei an, so erhält diese Datei normalerweise die Gruppenmitgliedschaft der primären Gruppe des Users, der sie eben angelegt hat. Das führt schnell zum Chaos, wenn z.B. mehrere User zusammen an einem Projekt arbeiten. Alle diese User sind Gruppenmitglieder einer bestimmten Gruppe, aber sie haben diese Gruppe nicht als primäre Gruppe. Das heißt, es kann sein, daß die einzelnen User die Dateien der jeweils anderen Projektmitarbeiter nicht lesen können. Wenn dieses Verzeichnis aber der gemeinsamen Gruppe gehört und eben das Substitute GroupID Bit darauf gesetzt ist, dann werden Dateien in diesem Verzeichnis grundsätzlich unter der GruppenID abgespeichert, der das Verzeichnis gehört. Mit diesem Mechanismus sind Arbeitsverzeichnisse für bestimmte Projektgruppen realisierbar.

Sticky Bit
  Das Sticky Bit hat nur eine Bedeutung für Verzeichnisse. Oben wurde schon das Problem erwähnt, daß ein User, der Schreibrecht auf ein Verzeichnis hat, innerhalb dieses Verzeichnisses alle Dateien löschen kann, auch wenn sie ihm nicht gehören und er keinerlei Rechte auf diese Dateien besitzt. Das wird durch das Sticky Bit verhindert.

  Ein Verzeichnis in dem jeder User Schreibrecht haben muß, wie etwa das /tmp-Verzeichnis, sollte unbedingt dieses Bit gesetzt haben. Ansonsten kann ein böswilliger User dort die Dateien anderer User löschen.

  Das gesetzte Sticky-Bit wird vom ls -l Kommando durch ein t statt des x in der Kategorie "Rechte des Restes der Welt" dargestellt.

Um diese speziellen Rechte auch numerisch darzustellen, wird vor den oben genannten "normalen" Rechten noch eine Oktalziffer angefügt, so daß sich das folgende Bild ergibt:

Sonderrechte | Eigentümer | Gruppenmitglied | Rest der Welt
--- | --- | --- | ---
`SUID` | `SGID` | `Sticky` | `r` | `w` | `x` | `r` | `w` | `x` | `r` | `w` | `x`
`4` | `2` | `1` | `4` | `2` | `1` | `4` | `2` | `1` | `4` | `2` | `1`

Ein Recht von 4755 bedeutet also, daß das Substitute UserID Bit gesetzt ist (4), der Eigentümer Lese-, Schreib- und Ausführungsrechte (1+2+4=7) hat während sowohl Gruppenmitglieder, als auch der Rest der Welt nur Lese- und Ausführungsrecht (1+4=5) besitzen.

### Ändern von Zugriffsrechten mit chmod

Um die oben beschriebenen Rechte vergeben bzw. ändern zu können existiert das Programm chmod (change mode). Es erlaubt, die Rechte von Dateien und Verzeichnisse zu verändern. Die prinzipielle Anwendung ist einfach:

`chmod [Optionen] Modus Datei(en)`

Die wichtigste Option ist dabei `-R` oder `--recursive`, mit dem ganze Unterverzeichnisse mit allen Dateien darin auf einmal bearbeitet werden können.

Als Modus kann entweder ein numerischer, oder ein symbolischer Modus angegeben werden. Der numerische Modus entspricht genau dem, was im letzten Abschnitt dieser Seite beschrieben wurde, er wird hier nicht nochmal erklärt. Nur ein kurzes Beispiel noch, der Aufruf

      chmod 644 foo.txt

würde der Datei `foo.txt` ein Zugriffsrecht von `rw-r--r--` geben. Mit numerischem Modus ist grundsätzlich immer ein absoluter Wert gesetzt, egal, welche Rechte vorher gesetzt waren.

Der symbolische Modus besteht aus einer Angabe der Rechte durch Buchstaben. Die Grundsätzliche Form ist:

`[ugoa] +|-|= [rwxstugo], ...`

Das führende Zeichen steht für die zu verändernde Kategorie, u steht für User (Eigentümer), g für group (Gruppenmitglied), o für other (Andere) und das a steht für all (Alle). Wird dieses führende Zeichen weggelassen, dann wird standardmäßig a (Alle) angenommen.

Vorsicht, oft wird diese Angabe verwechselt und das o mit dem Begriff Owner (Eigentümer) verwechselt. Das kann fatale Folgen haben, weil man dann die Rechte, die man eigentlich dem Eigentümer geben will, dem Rest der Welt verleiht!

Das folgende Rechenzeichen +, - oder = beschreibt, ob ein Recht den bestehenden Rechten hinzugefügt (+) werden soll, davon abgezogen (-) werden soll oder absolut (=) gesetzt werden soll.

Dem Rechenzeichen folgt die Angabe der zu setzenden (oder addierenden oder subtrahierenden) Rechte in der Form einer Zeichenkette, die aus den Buchstaben r,w,x,s,t,u,g,o besteht. Dabei meinen r, w und x wie üblich Read, Write und Execute. Wird dem User das s-Recht gesetzt, so meint das das Substitute UserID Bit (beispielsweise durch `u+s`), bekommt hingegen die Gruppe dieses Recht, so ist das Subtitute GroupID Bit gemeint (`g+s`). Das t steht für das Sticky-Bit und kann nur dem Rest der Welt vergeben werden (`o+t`).

Folgen dieser Angabe noch ein u, g oder o, so ist dies ein Ausschlußkriterium in Verbindung mit dem a am Anfang. Das nachgestellte u, g oder a schützt also die Rechte der User, Gruppenmitglieder bzw. Anderen vor Veränderung.

Das ganze kann jetzt mehrmals hintereinander angewandt werden, indem mehrere solcher Modi durch Kommas getrennt angegeben werden. So ist es etwa möglich zu schreiben:

      chmod u=rwx,g=rx,o-rwx foo

um dem Programm foo das Recht `rwxr-x---` zu setzen. Gewöhnlich tut man sich aber in diesem Fall leichter mit einer numerischen Angabe (hier 750).

Das praktische an der symbolischen Angabe von Modi ist die Fähigkeit, bestimmte Rechte auf die bestehenden Rechte aufzuaddieren bzw. sie von den bestehenden Rechten abzuziehen. Ein einfaches `+x` bedeutet z.B., daß allen drei Kategorien User, Group und Other ein Ausführungsrecht zu den schon vorhandenen Rechten gegeben wird.

Wird als Option ein -R oder ein --recursive angegeben, so verändert chmod die Rechte eines ganzen Verzeichnisbaums, inclusive aller enthaltenen Dateien und Unterverzeichnisse.

### Voreingestellten Zugriffsmodus mit umask bestimmen

Es bleibt jetzt natürlich die Frage, welche Zugriffsberechtigungen beim Anlegen einer Datei verwendet werden. Um das festzulegen, kennt Unix das Kommando umask, dessen Anwendung aber etwas merkwürdig ist.

Der Befehl umask erwartet eine Maske als Parameter, die sich auf den Zugriffsmodus bezieht, den neu zu erstellende Dateien bekommen sollen. Das Wort Maske bedeutet, daß nicht die Werte eingegeben werden, die gesetzt werden sollen, sondern umgekehrt, die Werte, die nicht gesetzt (maskiert) werden sollen. Die einfachste Möglichkeit besteht darin, die gewünschten oktalen Werte jeweils von 7 abzuziehen:

Wollen wir z.B. dafür sorgen, daß alle unsere Dateien die Zugriffsberechtigung `rw-r-----` bekommen, also Lese-und Schreibrecht für den Eigentümer, Leserecht für Gruppenmitglieder und keine Rechte für den Rest der Welt, dann entspräche das der oktalen Darstellung 640.

Die dafür notwendige umask wäre dann:

        7-6=1
        7-4=3
        7-0=7

Mit dem Befehl

      umask 137

würden also alle Dateien, die wir anlegen die gewünschte Zugriffsberechtigung 640 bekommen. Das hat noch einen kleinen Haken, weil die Verzeichnisse, die wir erstellen würden auch diesen Modus bekämen. Damit wäre für uns selbst das Durchsuchungsrecht (x) nicht gesetzt. Linux hat aus diesem Grund dafür den Mechanismus entwickelt, daß selbst wenn im umask-Kommando das x-Recht gesetzt ist, beim Erzeugen von normalen Dateien dieses Recht nicht gesetzt wird, beim Erzeugen von Verzeichnissen hingegen schon. Ein vernünftiges umask-Kommando setzt also zumindestens für den Eigentümer auch das x-Recht. Damit wäre ein typischer Wert für umask z.B. 022 (`rwxr-xr-x`) oder 027 (`rwxr-x---`).

Neben dieser umständlichen Methode gibt es aber auch die symbolische Form, die die Rechte direkt bezeichnet. Sie wird in der Form `u=...,g=...,o=...` eingegeben, wobei für ... immer die entsprechenden Rechte eingesetzt werden. Also würde der Befehl

      umask u=rwx,g=rx,o=

die gleiche Wirkung haben wie

       umask 027

Typischerweise steht eine umask-Anweisung in einer der Shell-Startdateien wie z.B. `/etc/profiles` oder `~/.profile`. Jeder User kann seine Voreinstellung also selbst einstellen, eine der wenigen Möglichkeiten, mit denen er dem Systemverwalter ins Handwerk pfuschen kann, wenn der versucht, sein System sicher zu machen. Allerdings bezieht sich diese Einstellung ja nur auf die neu anzulegenden Dateien des jeweiligen Users...

### Erweiterte Dateiattribute im EXT2-Dateisystem

Dateien auf EXT2-Dateisystemen besitzen neben den oben genannten Attributen noch weitere, die einen zusätzlichen Schutz bieten können. Diese Attribute können mit dem Befehl lsattr angezeigt und mit chattr verändert (gesetzt) werden.

Die wichtigsten dieser Attribute sind:

a (append)
  Eine Datei mit a-Attribut kann schreibend nur im Anhängen-Modus geöffnet werden. Das bedeutet, daß ein User, der Schreibrecht auf diese Datei hat, zwar Daten an das Ende der Datei anhängen kann (etwa durch die Verwendung der >>-Umleitung), jedoch keine Veränderungen am bestehenden Inhalt der Datei vornehmen darf. Nur der Superuser kann dieses Attribut setzen oder entfernen.
i (immutable)
  Eine Datei mit gesetztem i-Attribut kann nicht modifiziert werden. Sie kann weder gelöscht, noch umbenannt werden, es kann kein Hardlink auf sie angelegt werden und keine Daten können angehängt werden. Nur der Superuser kann dieses Attribut setzen oder entfernen.
s (save-delete)
  Wenn eine Datei das s-Attribut gesetzt hat, werden alle Blöcke dieser Datei beim Löschen der Datei mit Nullzeichen überschrieben. Dadurch ist die Datei auch durch Methoden wie dem Dateisystemdebuger nicht wieder herstellbar oder ihr Inhalt ist nicht mehr einsehbar, wenn sie einmal gelöscht wurde.

Eine Liste aller möglichen Attribute entnehmen Sie der Handbuchseite von chattr.