Reconnaissance

Du hast nun die volle Kontrolle über das LUPFER-System. Jetzt geht es darum, dass du einen möglichst langfristigen Zugriff erhältst, um weitere Angriffe durchzuführen. Damit ersparst du dir, jedes Mal die komplette Kette von Schwachstellen ausnutzen zu müssen. Schließlich ist auch denkbar, dass die SSTI-Schwachstelle in der Webapplikation eines Tages gepatcht würde und der Zugang damit nicht mehr möglich wäre.

Welche Möglichkeiten gibt es nun, einen persistente Zugriffsmöglichkeit zu schaffen? Das sind:

  1. Authentifizierungsdaten des aktuellen Benutzers stehlen
  2. Eigenen Benutzer anlegen
  3. Cronjob anlegen

Wir konzentrieren uns hier auf den ersten Punkt. Da du nun Zugriff mit Root-Rechten hast, solltest du die Phase der Reconnaissance erneut durchführen und Verzeichnisse untersuchen, auf die du vorher keinen Zugriff hattest.

Stelle wieder mit dem Befehl nc -lp <Port> eine Reverse Shell zum LUPFER her. Dafür musst du die Seite https://lupfer.pentest.samsmart.hosts.openinc.de/usermanagement erneut laden.

Du hast nun also Zugriff auf die Home-Verzeichnisse der Benutzer root und ubuntu. Das versteckte Verzeichnis /root/.ssh ist dabei interessant. In diesem Verzeichnis werden Konfigurationsdateien und kryptographische Schlüssel abgelegt, die für den Dienst Secure Shell (ssh) eingesetzt werden. Die beiden Dateien id_rsa und id_rsa.pub wirst du dir gleich noch genauer ansehen.

Enumeration

Auf die Reconnaissance folgt die Enumeration. Hier soll es nur darum gehen, einen direkten Zugriff mit Root-Rechten zu etablieren. Eine Möglichkeit besteht darin, Authentifizierungsdaten des Benutzers root zu ermitteln.

Passwort-Informationen werden in der Datei /etc/shadow gespeichert, auf die nur der Benutzer root Zugriff hat. Jeder Eintrag in /etc/shadow besteht aus neun Feldern, die durch einen Doppelpunkt : getrennt sind:

  • Benutzername wie in /etc/passwd
  • Verschlüsseltes Passwort bzw. * oder !, wenn kein Einloggen mit Passwort möglich ist
  • Datum der letzten Änderung des Passworts
  • Mindestalter des Passworts, bevor es geändert werden darf
  • Maximalalter des Passworts, bis der Benutzer es ändern muss
  • Warnzeit vor Ablauf des Maximalalters, in der der Benutzer gewarnt wird, dass sein Passwort abläuft
  • Inaktivitätszeit, in der das Passwort bei Inaktivität des Benutzers gültig bleibt, obwohl das Maximalalter erreicht wurde
  • Ablaufdatum, an dem das Benutzerkontoendgültig gesperrt wird
  • Reserviertes Feld für zukünftige Erweiterungen

Für den Benutzer root ist also kein Passwort hinterlegt. Er muss sich daher also auf anderem Wege authentifizieren zum Beispiel über ein Public-Key-Verfahren, wie es in der Abbildung für das Protokoll SSH dargestellt ist:

SSH public key authentication
Authentifizierung des Clients mittels Public-Key-Verfahren für das Protokoll SSH

Die Schritte zur Authentifizierung des Clients läuft beim Protokoll SSH folgendermaßen ab:

  1. Der Client sendet seinen Benutzernamen an den Host.
  2. Der Host prüft, ob dieser Benutzer authoriziert ist, eine Verbindung herzustellen. Wenn dies der Fall ist, ist sein öffentlicher Schlüssel in der Datei /.ssh/authorized_keys abgelegt.
  3. Der Host sendet anschließend seinen eigenen öffentlichen Schlüssel an den Client.
  4. Der Client prüft, ob der Host bekannt und daher in der Datei .ssh/known_hosts abgelegt ist. Ist dies nicht der Fall, wird der Benutzer gefragt, ob er sich mit dem Host verbinden möchte.
  5. Client und Host handeln anschließend Parameter für eine gesicherte Verbindung aus.
  6. Der Client sendet eine mit seinem privaten Schlüssel signierte Nachricht an den Host. Die Nachricht besteht unter anderem aus dem Benutzernamen und dem öffentlichen Schlüssel des Clients.
  7. Der Host verifiziert die Signatur der Nachricht mit dem öffentlichen Schlüssel des Clients.
  8. Anschließend ist der Client authentifiziert und der eigentliche Datenaustausch kann beginnen.

Das Public-Key-Verfahren zur Authentifizierung bei SSH verwendet die asymmetrische Verschlüsselung.

Bei der asymmetrischen Verschlüsselung gibt es zwei Schlüssel: einen öffentlichen Schlüssel (Public Key) und einen privaten Schlüssel (Private Key). Der öffentliche Schlüssel wird verwendet, um Nachrichten zu verschlüsseln, während der private Schlüssel benötigt wird, um diese Nachrichten zu entschlüsseln. Der Schlüsselunterschied sorgt dafür, dass nur der Besitzer des privaten Schlüssels in der Lage ist, die verschlüsselte Nachricht zu entschlüsseln.

Der Client wird bei SSH also über die Nachricht authentifiziert, die er im 6. Schritt an den Host sendet und die er über seinen privaten Schlüssel signiert. Für die Signatur verschlüsselt der Client den Hashwert der Nachricht mit seinem privaten Schlüssel:

Signing a message
Digitale Signatur

Nachdem er die signierte Nachricht des Clients erhalten hat, verifiziert der Host die Signatur:

Verifying a signature
Verifizierung einer digitalen Signatur

Dafür berechnet er einerseits selbst den Hashwert der Nachricht. Andererseits entschlüsselt er die Signatur mit dem öffentlichen Schlüssel des Clients und ermittelt so den Hashwert, mit dem die Signatur gebildet wurde. Beide Hashwerte vergleicht er anschließend. Sind sie gleich, dann ist die Signatur valide und der Client besitzt den privaten Schlüssel, der zum öffentlichen Schlüssel gehört.

Die Reconnaissance mit Root-Rechten hatte ergeben, dass es das versteckte Verzeichnis /root/.ssh gibt. Schau dir dies nun noch einmal an.

Bei den Dateien ìd_rsa und id_rsa.pub handelt es sich also um einen privaten und einen öffentlichen Schlüssel.

Exploitation

Beide Schlüssel wirst du nun auf diesen Computer kopieren. Dafür brauchst du weiter den Zugriff auf den LUPFER im Terminal 1 und Zugriff auf das lokake System im folgenden Terminal. Die Schritte sind dann:

  1. Kopiere den privaten Schlüssel vom LUPFER. Führe dafür in der Reverse Shell folgenden Befehl aus:
    cat /root/.ssh/id_rsa
    Markiere den Schlüssel und kopiere ihn über die rechte Maustaste in die Zwischenablage.
  2. Auf dem lokalen System gibst du den kopierten Schlüssel aus:
    echo "
    Füge dann über die rechte Maustaste den Schlüssel aus der Zwischenablage ein.
  3. Belasse den Cursor, wo er ist, auch wenn du dann Zeichen überschreibst. Schließe die Ausgabe mit " ab und schreibe den Schlüssel auf dem lokalen System in eine Schlüsseldatei:
    " > ~/.ssh/id_rsa
  4. Schränke die Rechte für den privaten Schlüssel auf dem lokalen System ein, da ihn SSH ansonsten nicht akzeptiert:
    chmod u=rw,go= ~/.ssh/id_rsa
    Damit hat der Besitzer Lese- und Schreibrechte, während die Gruppe und Andere keine Berechtigungen haben.
  5. Hänge den öffentlichen Schlüssel auf dem LUPFER anschließend der Datei authorized_keys an:
    cat id_rsa.pub >> authorized_keys
    Damit wird der Schlüssel der Datei hinzugefügt. Existiert sie noch nicht, wird sie erzeugt.

Wenn alles geklappt hat, solltest du dich anschließend über Secure Shell (SSH) mit dem LUPFER verbinden können:

ssh -i ~/.ssh/id_rsa <user>@<IP>

Der Befehl ssh initiiert dabei die Verbindung zum Server, wobei die Option -i den Pfad zur Identitätsdatei (privater Schlüssel) enthält. <user>@<IP> gibt den Benutzernamen und die Zieladresse des Servers an.

Damit hast du nun permanenten Zugriff auf den LUPFER und kannst von hier aus auch Angriffe auf weitere Geräte im Netzwerk starten. Wir brechen hier aber einmal ab und wenden uns im nächsten Abschnitt der Firmware zu.