File Permissions

Benutzer und Gruppen im System können Dateien und Verzeichnisse besitzen. Besitzer und Gruppen können Lese, Schreib- (und damit Lösch-) und/oder Ausführungsrechte auf Dateien besitzen; bei Verzeichnissen wird das Execute-Recht als Berechtigung zum Wechsel in das Verzeichnis genutzt.

Neben dem Benutzer („user“, „u“) und der Gruppe („group“, „g“) gibt es noch den Rest der Welt („others“, „o“). „a“ bezeichnet kurz „all“, die Kurzform für „ugo“.

User, Group und Others können wie erwähnt unterschiedliche Berechtigungen auf Dateien und Verzeichnisse besitzen: read, write, execute („rwx“).

Folgende Befehle verwalten die Datei-Berechtigungen:

  • chown: Change Owner, ändert den Besitzer einer Datei/eines Verzeichnisses:

  • chgrp: Change Group, ändert die Gruppe einer Datei/eines Verzeichnisses:

  • chmod: Change Mode, ändert die Berechtigungen für User, Group und Others

Die drei Berechtigungsstufen werden den drei Besitzergruppen wie folgt im Klartext zugeordnet:

su - linus

cd /tmp
touch myscript
chmod u=rwx,g=rw,o=r myscript

Die Ausgabe -rwxrw-r--. 1 linus sales 128 Dec 24 19:20  myscript von ls -l bedeutet:

-rwxrw-r--.
Lesen als - rwx rw- r-- .
Erste Stelle: mit „-“ wird eine Datei symbolisiert. Andere Angaben wären „d“ für Directory oder „l“ für einen symbolischen Link.
Die nächsten drei Stellen beschreiben die Berechtigungen des Besitzer linus. Er besitzt alle Rechte („rwx“) auf die Datei.
Die nächsten drei Stellen beschreiben die Berechtigungen der Gruppe sales; sie besitzt Lese- und Schreibrechte.
Alle anderen besitzen Leserechte.
Letztes Zeichen: der „.“ bedeutet, dass keine erweiterten Berechtigungen (ACL) gesetzt sind („+“ = ACL gesetzt).
1

Anzahl der harten Links auf die Datei (dort immer mindestens 1); bei Verzeichnissen Summe der enthaltenen Dateien und Unterverzeichnisse auf der ersten Ebene.

linus

Besitzer der Datei.

sales

Gruppe der Datei.

128

Grösse in Bytes.

Dec 24 19:20

Zeitpunkt der letzten Änderung

myscript

Name der Datei bzw. des Verzeichnisses.

Die rwx-Berechtigungen lassen sich auch durch Werte ausdrücken, wobei 4 = read, 2 = write und 1 = execute entspricht. In der Summe ergibt sich demnach:

Wert (binär)

Ausprägung

0 (000)

---

1 (001)

--x

2 (010)

-w-

3 (011)

-wx

4 (100)

r--

5 (101)

r-x

6 (110)

rw-

7 (111)

rwx

Der Schlüssel zum Setzen von Datei- und Verzeichnisberechtigungen ist der Befehl chmod. Er kennt eine Klartext- als auch die Bitnotation:

chmod u=rwx,g=rw,o=r myscript
chmod 764 myscript

In der Klartext-Notation werden bestehende Rechte mit „=“ überschrieben, mit „+“ ergänzt und mit „-“ entfernt.

chmod uo+wx,g=r test.txt
chmod u+x,u-w test.sh

Den Besitzer und die Gruppe einer Datei oder eines Verzeichnisses wechselt man so (drei Beispiele):

chown new_user filename
chgrp new_group filename
chown new_user:new_group filename

Alle Befehle lassen sich rekursiv über den Parameter -R bzw. --recursive auf ganze Verzeichnisbäume anwenden. Für chmod sollte dann das Executable-Flag nur mit X (statt x) angegeben werden - es sorgt dafür, dass nur Verzeichnisse oder Dateien, die bereits in irgendeiner Form ausführbar sind, das Executable-Flag erhalten.

-h bzw. --no-dereference ändert den Besitzer/die Gruppenzugehörigkeit eines symbolischen Links. Ohne Angabe dieses Parameters wird die Eigentümerschaft der darunter liegenden Datei modifiziert.

Setuid, Setgid, Sticky Bit

Darüber hinaus existieren noch drei Sonderrechte: Setuid, Setgid und das Sticky Bit.

Eine ausführbare Datei, die das Setuid-Bit besitzt, läuft unter der User-ID des Besitzers der Datei; ein Verzeichnis mit Setuid-Bit setzt für neu angelegte Dateien den Besitzer auf den des Verzeichnisses (deswegen „set“uid).

Für Setgid gilt das gleiche wie für Setuid, nur auf Basis der Gruppe.

Das Sticky Bit verhindert bei Verzeichnissen, dass Benutzer die Dateien anderer Benutzer löschen dürfen. Oder anders: nur der Besitzer der Datei darf diese in einem Sticky-Verzeichnis löschen, alle anderen (auch mit Schreibberechtigung) nicht.

Die Bit-Wertigkeiten hier sind:

  • setuid: 4 = s

  • setgid: 2 = s

  • sticky: 1 = t

Beispiel, in dem das Setgid-Bit auf ein Verzeichnis gesetzt wird:

mkdir /share
useradd linus
groupadd sales
chown linus:sales /share
chmod u+rwx,g=rxs,o= /share
chmod 2750 /share

Besitzer linus = rwx, Gruppe sales = rx inkl. Setgid, alle anderen keine Rechte - in diesem Verzeichnis neu erstellte Inhalte gehören demnach der Gruppe sales.

Das gleiche Beispiel mit Setuid und Setgid-Bit:

chmod u+rwxs,g=rxs,o= /share
chmod 6750 /share

Man beachte die Ausgabe des ls -l-Kommandos: ein kleines s bedeutet „shared + execute“, ein grosses S bedeutet „shared, ohne execute-Recht“.

Man entzieht einer Datei oder einem Verzeichnis alle Rechte mit:

chmod a-rwxs /share

So kopiert man die Berechtigungen von file1 auf file2:

chmod --reference file1 file2

Access Control Lists (ACL)

Die Datei-Berechtigungen sind einfach und effektiv, reichen aber nicht immer aus. Bei gehobenen Ansprüchen verwendet man Access Control Lists (ACL), um Benutzern und Gruppen den Zugriff auf Dateien feingranuliert zu erlauben oder zu verweigern. Um ACLs für ein Dateisystem zu aktivieren, musste man bis RHEL 6 dem entsprechenden Eintrag in der /etc/fstab in der Optionen-Spalte ein acl hinzufügen. Ab RHEL 7 sind ACLs für Ext4 und XFS bereits ab Werk aktiv.

Um zu sehen, welche ACLs auf Verzeichnisse oder Dateien gesetzt sind, verwendet man getfacl filename. setfacl wird verwendet, um diese zu setzen:

getfacl filename.txt

# find all files with ACLs set
getfacl --recursive --skip-base --absolute-names / | sed --quiet 's/^# file: //p'

setfacl --modify u:linus:rw filename.txt
setfacl --modify g:sales:r filename.txt

Bemerkung

In RHEL 8+ sind ACLs nur bei Verzeichnissen und Dateien von Journald aktiv. Beispiel:

  • /run/log/journal/b1f9cb121bef4b4bae309d91b95b3257

  • /run/log/journal/b1f9cb121bef4b4bae309d91b95b3257/system.journal

  • /run/log/journal/b1f9cb121bef4b4bae309d91b95b3257/system@*.journal~

  • /run/log/journal/b1f9cb121bef4b4bae309d91b95b3257/system@0005f37eb1b747d2-d54e9076fb6d2125.journal~

  • /run/log/journal/60c72a5c2d9e4835a50576c0069ea0a0

  • /run/log/journal/60c72a5c2d9e4835a50576c0069ea0a0/system.journal

ACL entfernen:

# remove just the last rule from above
setfacl --modify g:sales:0 filename.txt
# remove all ACLs
setfacl --remove-all filename.txt

In folgendem Beispiel sollen neu erstellte Dateien in einem Verzeichnis rw-Berechtigungen für die Gruppe erhalten:

setfacl --default --modify=g::rwx mydir

Noch ein erweitertes Beispiel, um Benutzer, Gruppe und - wichtig - Standard-Berechtigungen abseits von umask für ein Verzeichnis zu setzen.

mkdir mydir
chmod a-rwxs,u+rwx,g+rwxs mydir
chown :sales mydir
setfacl --default --modify=u::rwx,g::rwx,o::- mydir

Dateien erhalten so rw-rwd--, Verzeichnisse rwxrwsd-. Zugehörige Gruppe ist fortan immer sales. Deren Mitglieder können uneingeschränkt mit diesem Verzeichnis arbeiten.

Tipp

Aus der Praxis: Wie gibt man einer Benutzergruppe, die keine sudo-Rechte erhalten soll, unter RHEL Zugriff auf bestimmte Logdateien?

Wir haben das mit ACLs gelöst. Im Beispiel erhält die Gruppe „customer_dev“ Zugriff auf zwei Logdateien:

setfacl --modify g:customer_dev:r /var/log/messages
setfacl --modify g:customer_dev:rx /var/log/php-fpm
setfacl --modify g:customer_dev:r /var/log/php-fpm/error.log

Falls also keine --default ACL gesetzt wird, nicht vergessen, die passenden logrotate-Konfigurationsdateien anzupassen, damit der Zugriff nach dem Rotieren wieder erlaubt wird:

/var/log/messages
/var/log/php-fpm/error.log
{
    postrotate
        /usr/bin/setfacl --modify g:customer_dev:r /var/log/messages
        /usr/bin/setfacl --modify g:customer_dev:r /var/log/php-fpm/error.log
    endscript
}

Datei-Berechtigungen am praktischen Beispiel

Alle Benutzer dürfen das Verzeichnis /share lesen, Benutzer linus besitzt darin den Ordner project-linus mit rwx-Rechten, auf das auch die sales-Gruppe schreibend zugreifen können soll.

Der Projekt-Ordner muss also der Gruppe sales gehören; mit dem Setgid-Bit wird sichergestellt, das auch in Zukunft neu angelegte Dateien diese Gruppenzugehörigkeit erben. Der root-User geht dafür folgendermassen vor:

mkdir -p /share/project-linus
chown linus:sales /share/project-linus

share besitzt direkt nach dem Anlegen „rwx, rx, rx, root:root“, project-linus nach dem chown „rwx, rx, rx, linus:sales“. Es wird noch das Setgid-Bit benötigt, sales soll noch schreiben dürfen, und alle anderen möchten wir ausschliessen:

chmod g+ws,o= /share/project-linus

Jede darin angelegte Datei wird fortan der Gruppe sales zugeordnet. Soll linus auch Dateien bearbeiten dürfen, die Benutzer aus der Gruppe sales angelegt haben, benötigt man entweder das Setuid-Bit (damit erben alle Dateien den Besitzer des übergeordneten Verzeichnisses, linus), oder man fügt linus der sales-Gruppe hinzu.

Warum 777 und 666 keine gute Idee ist

666 ermöglicht es jedem Benutzer des Systems, die damit geflaggten Dateien zu verändern, und im Fall von 777 sogar auszuführen.

Schlechtes Beispiel: Verzeichnis mit 777 und darin eine Datei mit 666 erstellen.

[user ~] $ mkdir test
[user ~] $ chmod 0777 test
[user ~] $ cd test/
[user ~/test] $ touch test.txt
[user ~/test] $ chmod 0666 test.txt

Ein anderer Benutzer des Systems kann diese Dateien nun manipulieren - neue Dateien ablegen, vorhandene Dateien verändern usw..

[hacker ~] $ cd /home/user/test
[hacker /home/user/test] $ ll
total 8.0K
drwxrwxrwx 2 user user 4.0K 2021-01-01 12:00 .
drwxr-xr-x 3 user user 4.0K 2021-01-01 12:00 ..
-rw-rw-rw- 1 user user    0 2021-01-01 12:00 test.txt
[hacker /home/user/test] $ touch bad
[hacker /home/user/test] $ echo "OVERWRITE" > test.txt
[hacker /home/user/test] $ cat test.txt
OVERWRITE

Dateien und Verzeichnisse schützen

Wer Dateien und Verzeichnisse vor (versehentlichem) Bearbeiten, Umbenennen, Verschieben oder Löschen schützen möchte - und das für alle Benutzer, auch für root - verwendet chattr. Dies ist zwar abhängig vom verwendeten Dateisystem, funktioniert aber zumindest auf Ext3, Ext4 und XFS identisch. Das i-Attribut verhindert das Modifizieren:

Attribut setzen:

chattr +i myfile
chattr +i mydir

Attribut entfernen:

chattr -i myfile
chattr -i mydir

Attribute auflisten:

lsattr

umask

Wird ein Verzeichnis neu erstellt, vergibt Linux zunächst die Berechtigung 0777 (also drwxrwxrwx), bei Dateien 0666 (-rw-rw-rw-). Die umask überschreibt anschliessend Berechtigungen auf neu erstellte Dateien und Verzeichnisse. Eine umask kann nur systemweit und nicht auf einzelne Verzeichnisse gesetzt werden.

Zur Erinnerung:

  • 1: Execute

  • 2: Write

  • 4: Read

In RHEL ist die umask für reguläre Benutzer auf 0002 gesetzt - es wird also das write-Bit bei „others“ gelöscht. Reguläre Benutzer sind Benutzer mit einer User-ID ab 200, bei denen der Benutzername und die Primary Group identisch gesetzt sind.

root besitzt die umask 0022, es wird also das write-Bit für „group“ und „others“ gelöscht.

umask abfragen - in oktaler und symbolischer Schreibweise:

# octal
umask
# symbolic
umask -S

Wer einfach nur die Standard-Berechtigungen für ein Verzeichnis ändern möchte, arbeitet besser mit ACLs (siehe weiter unten) - die umask gilt immer für das ganze System.

Hardening

Die umask kann für Benutzer und für root auf 0027 geändert werden (je nach Anforderung in /etc/login.defs, /etc/profile, /etc/bashrc, ~/.bash_profile oder ~/.bashrc), welche das write-Bit bei „group“ und sämtliche Berechtigungen für „others“ entfernt.

Erweitertes Beispiel für das Setzen einer umask:

/etc/profile.d/set_umask.sh
# Overrides default umask configuration
if [ $UID -gt 199 ] && [ "$(id -gn)" = "$(id -un)" ]; then
    umask 007
else
    umask 022
fi

Troubleshooting

So setzt man Berechtigungen systemweit auf Dateien und Verzeichnisse:
# Directories: rwxr-xr-x (755)
find . -type d -exec chmod u=rwx,g=rx,o=rx "{}" \;

# Files: rw-r--r-- (644)
find . -type f -exec chmod u=rw,g=r,o=r "{}" \;
Was macht man, wenn man chmod die eigenen Ausführungsrechte über chmod -x chmod entzogen hat?

Dann „borgt“ man sich die Ausführungsrechte beispielsweise von ls:

cp --preserve /usr/bin/ls /tmp/chmod.tmp
cat /usr/bin/chmod > /tmp/chmod.tmp
cp --preserve /tmp/chmod.tmp /usr/bin/chmod

Built on 2023-03-17