Von Michael Gisbers 1. August 2022
tar - Archiv zu packen, dieses im Netz abzulegen, den Rechner
zu bereinigen und über das Archiv wiederherzustellen.
Dabei werden viele Tools wie fdisk/gdisk, mkfs, mount, tar und
grub-install benötigt um den Datenträger vorzubereiten, die Partitionen zu
formatieren und die Dateisysteme wieder richtig einzuhängen um dort das Archiv
zu entpacken. Nach der Installation des GRUB läuft dann in der Regel das System
wieder und kann getestet werden.
Leider kommt es immer mal wieder dazu, daß der Versuch als Benutzer einen ping
in dem neu aufgebauten System einen Fehler meldet.
user@linux $ ping gisbers.de
ping: socket: Operation not permitted
Woher kommt der Fehler? Das System ist korrekt hochgefahren und auch die Netzwerkumgebung läuft einwandfrei, aber es kommt - egal ob über eine IP - Adresse oder einen DNS-Namen aufgerufen - immer die gleiche Fehlermeldung.
Bei einem genauen Blick auf die Fehlermeldung wird klar, daß ping versucht
eine Verbindung aufzubauen, die er nicht aufbauen darf. Dazu muss man hinter
die Aufgabe des Befehls schauen: Er soll einem per IP - Netzwerk erreichbaren
Gerät eine Nachricht des Typs 8 (Echo Request) über das Internet Control
Message
Protocol
(ICMP) und auf die Antwort des anderen Gerätes warten. Dieses schickt - solange ihm das
nicht verboten ist oder eine Firewall blockt - eine Antwort mit einer Nachricht
Typ 0 ICMP (Echo Reply) zurück.
Um die Nachrichten versenden und Antworten zu empfangen muss ping in der Lage
sein einen passenden Socket für das Senden und einen für den Empfang der
Antwort zu öffnen.
Und genau hier wird die Fehlermeldung generiert. Dem Befehl ping fehlt
das Recht diese Sockets zu öffnen. Wird der Befehl als Benutzer root
aufgerufen funktioniert er wie gewohnt.
Was dem Benutzer fehlt ist das Recht Sockets für ICMP zu erstellen. Für die Protokolle TCP und UDP - bei Ports größer 1023 - darf er das und damit auch eigene Programme starten, die sie benutzen.
Sehr lange Zeit haben die Distributionen den Befehl ping über ein SetUID zu
einem Befehl gemacht, der als Benutzer root läuft. Dazu muss der Besitzer des
Befehls der Benutzer root und das s (SetUID) - Flag für den Benutzer
gesetzt sein. Zu sehen an dem kleinen s in den Zugriffsrechten.
user@linux $ ls -l /bin/ping
-rwsr-xr-x 1 root root 76568 22 Dez. 2021 /bin/ping
Mit den durch diese Einstellung vergebenen Rechten läuft der Befehl ping beim
Aufruf mit den effektiven Rechten des Benutzer root. Bedeutet, daß es möglich
ist durch Fehler innerhalb des Befehls z. B. andere Programme zu starten, die
dann auch direkt mit uneingeschränkten root Rechten laufen.
Das schöne an diesen Rechten ist, daß sie in einen tar Archiv
transportierbar sind und nach dem entpacken als Benutzer root wieder
vorhanden sind.
Allerdings wäre es sehr viel sinnvoller dem Befehl nur die benötigten Rechte
zum Erstellen der Sockets zu geben und nicht die vollen root Rechte.
Die root - Rechte sind
capabilities
(Fähigkeiten), die dem Benutzer root in einem Linux basierten System
zugewiesen sind. Im Gegensatz zu normalen Benutzern erhält root alle
capabilities, der Benutzer keine.
Schaut man durch die Liste der capabilities, dann findet man eine mit dem Namen CAP_NET_RAW.
CAP_NET_RAW
* Use RAW and PACKET sockets;
* bind to any address for transparent proxying.
Die Beschreibung verspricht, daß ein Zugriff auf RAW und Packet Sockets erlaubt ist. Zusätzlich erlaubt es auf beliebige Adressen zu binden.
Der neue Trick der Distributionen ist also dem Befehl ping die capability
CAP_NET_RAW zu geben und darüber nur ein eingeschränktes Recht zu
erhalten. Vorteil dieser Vorgehensweise: Bei einem Fehler im Befehl können
von ihm aufgerufene Programme davon nicht profitieren.
user@linux $ ls -l /bin/ping
-rwsr-xr-x 1 root root 76568 22 Dez. 2021 /bin/ping
user@linux $ getcap /bin/ping
/bin/ping cap_net_raw+p
Wie im Listing zu sehen ist gibt es über den Befehl ls keinen Hinweis darauf,
daß der Befehl mit zusätzlichen capabilities versehen ist. Erst mit dem Tool
getcap lassen sich die capabilities von Befehlen anzeigen.
Da diese in den erweiterten Attributen der Dateien gepeichert sind lassen sie
sich auch mit dem Befehl getfattr auslesen.
user@linux $ getfattr -n security.capability /bin/ping
# file: bin/ping
security.capability=0sAQAAAgAEAAAAAAAAAAAAAAAAAAA=
Genau diese erweiterten Attribute gehen bei einem normalen Backup per tar
verloren. tar kann sie also auch nach dem Entpacken nicht wiederherstellen.
Sollen diese Attribute mit in das Archiv, dann muss explizit --xattrs als
Parameter beim Erzeugen vorhanden sein. Aus Sicherheitsgründen stellt tar die
security.capability - Attribute nur wieder her, wenn dies explizit über den
Parameter --xattrs-include='security.capability' oder allgemeiner
--xattrs-include='*' für alle Attribute beim Entpacken angefordert ist.
Beispiel für das Packen und Entpacken des Befehls tar mit erweiterten
Attributen.
Bitte das Beispiel nicht in Live/Produktiv - Systemen ausprobieren
user@linux $ tar --xattrs -cvf /tmp/ping.tar /bin/ping
tar: Entferne führende „/“ von Elementnamen
/bin/ping
user@linux $ sudo tar --xattrs-include='*' -C / -xvf /tmp/ping.tar
bin/ping
Durch die beiden Befehle wird zunächst ein Archiv mit dem Befehl /bin/ping
und dessen erweiterten Attributen erzeugt und danach auf die gleiche Datei
zurückgeschrieben.
Allerdings überraschen immer mehr Distributionen und zeigen, daß es auch komplett anders geht.
Es kommen weder ein SetUID noch capabilities zum Einsatz. Trotzdem
funktioniert der Befehl ping für den normalen Benutzer.
Hier hilft der Kernel mit. Über den Parameter
/proc/sys/net/ipv4/ping_group_range bekommt der Kernel die Information
welcher Bereich an Gruppen IDs die Erlaubnis haben den Befehl ping ohne
weitere capabilities oder SetUID zu benutzen.
Obwohl der Parameter schon seit der Kernel Version 2.6.39 existiert findet er erst jetzt häufiger seinen Einsatz. Genaue Informationen dazu sind in der ICMP Manual Page zu finden.
ping_group_range (two integers; default: see below; since Linux
2.6.39)
Range of the group IDs (minimum and maximum group IDs,
inclusive) that are allowed to create ICMP Echo sockets.
The default is "1 0", which means no group is allowed to
create ICMP Echo sockets.
Bei Archlinux ist dieser Parameter so eingestellt, daß er für alle möglichen Gruppen IDs gilt.
user@linux $ cat /proc/sys/net/ipv4/ping_group_range
0 2147483647
Am sinnvollsten lässt sich der Eintrag über den Befehl sysctl verändern.
user@linux $ sudo sysctl -w net.ipv4.ping_group_range='0 2147483647'
net.ipv4.ping_group_range = 0 2147483647
Dies ist allerdings nicht persistent. Um es persistent und damit auch nach
einem Neustart direkt neu einzutragen wird die Zeile mit dem Parameter und Wert
in eine Datei unter /etc/sysctl.d/ abgelegt. Genauere Infos hierzu sind in
der sysctl Manual Page
zu finden.
Mit den nun bekannten Informationen im Hinterkopf lässt sich die Aufgabe für die Linux Administratoren neu gestalten und führt wieder zu einem Erfolgserlebnis.