Detect SAML Tokens in Microsoft Sentinel
Adversaries may forge SAML tokens with arbitrary permissions and lifetimes if they possess a valid SAML token-signing certificate. Known as 'Golden SAML,' this attack allows adversaries to authenticate to any service trusting a federated identity provider (IdP) without needing user credentials or MFA. Attackers typically extract the token-signing certificate from AD FS using the Distributed Key Manager (DKM) container in Active Directory, or establish a new rogue federation trust. The SolarWinds/SUNBURST campaign demonstrated this technique at scale, enabling attackers to forge SAML tokens for any cloud identity in Microsoft 365 and Azure AD.
MITRE ATT&CK
- Tactic
- Credential Access
- Technique
- T1606 Forge Web Credentials
- Sub-technique
- T1606.002 SAML Tokens
- Canonical reference
- https://attack.mitre.org/techniques/T1606/002/
KQL Detection Query
// T1606.002 — Golden SAML: Forged SAML Token Detection
// Three detection branches covering: (1) DKM cert extraction, (2) federation trust changes, (3) anomalous SAML sign-ins
let GoldenSAMLAlerts = union
//
// Branch 1: AD FS DKM Container Access (token-signing cert extraction via LDAP)
// Event 4662 fires when an object in Active Directory is accessed.
// The AD FS DKM container stores encrypted token-signing keys. Access by anything other
// than the ADFS service account is highly suspicious.
(
SecurityEvent
| where TimeGenerated > ago(24h)
| where EventID == 4662
| where (
(ObjectName has "ADFS" and ObjectName has "Program Data")
or ObjectName has "CryptoPolicy"
or Properties has "72e39547-7b18-11d1-adef-00c04fd8d5cd" // thumbnailPhoto GUID (stores DKM keys)
or Properties has "thumbnailPhoto"
)
| where SubjectUserName !endswith "$" // Exclude computer accounts (ADFS service account uses computer account)
| extend DetectionBranch = "DKM_Container_Access"
| extend RiskScore = 90
| project TimeGenerated, DetectionBranch, RiskScore,
AccountName = SubjectUserName, AccountDomain = SubjectDomainName,
Computer, EventID,
ObjectName, AccessedProperties = Properties,
OperationType
),
//
// Branch 2: Federation Trust Created or Modified in Azure AD
// Adding a new federation trust or changing a domain to federated allows an adversary
// to introduce a rogue IdP they control, enabling arbitrary token forgery.
(
AuditLogs
| where TimeGenerated > ago(24h)
| where OperationName in (
"Set domain authentication",
"Set federation settings on domain",
"Add unverified domain",
"Add verified domain",
"Update domain",
"Set company information"
)
| where Result =~ "success"
| extend ModifiedProperties = tostring(TargetResources[0].modifiedProperties)
| where ModifiedProperties has "Federated" or ModifiedProperties has "federationSettings" or OperationName has "federation"
| extend DetectionBranch = "Federation_Trust_Modified"
| extend RiskScore = 95
| extend AccountName = tostring(InitiatedBy.user.userPrincipalName)
| extend TargetDomain = tostring(TargetResources[0].displayName)
| project TimeGenerated, DetectionBranch, RiskScore,
AccountName, AccountDomain = "AzureAD",
Computer = "AzureAD", EventID = 0,
ObjectName = OperationName,
AccessedProperties = ModifiedProperties,
OperationType = TargetDomain
),
//
// Branch 3: Anomalous SAML-protocol Sign-ins with Elevated Risk
// Forged SAML tokens may generate sign-in events with unusual characteristics:
// high-risk state, sign-in from atypical locations, or impossible travel.
// Filter to SAML 2.0 protocol sign-ins flagged by Identity Protection.
(
SigninLogs
| where TimeGenerated > ago(24h)
| where AuthenticationProtocol =~ "saml20"
| where RiskLevelDuringSignIn in ("high", "medium")
or RiskState in ("atRisk", "confirmedCompromised")
or (ResultType == 0 and IsRisky == true)
| extend DetectionBranch = "Anomalous_SAML_Signin"
| extend RiskScore = case(
RiskLevelDuringSignIn =~ "high" or RiskState =~ "confirmedCompromised", 85,
RiskLevelDuringSignIn =~ "medium" or RiskState =~ "atRisk", 65,
50
)
| extend GeoInfo = strcat(tostring(LocationDetails.city), ", ", tostring(LocationDetails.countryOrRegion))
| project TimeGenerated, DetectionBranch, RiskScore,
AccountName = UserPrincipalName, AccountDomain = "AzureAD",
Computer = AppDisplayName, EventID = 0,
ObjectName = strcat("SAML SignIn: ", AppDisplayName),
AccessedProperties = strcat("Risk:", RiskLevelDuringSignIn, " Location:", GeoInfo, " IP:", IPAddress),
OperationType = AuthenticationProtocol
);
GoldenSAMLAlerts
| sort by RiskScore desc, TimeGenerated desc Detects Golden SAML attacks (T1606.002) via three correlated branches. Branch 1 identifies direct access to the AD FS Distributed Key Manager (DKM) container in Active Directory (Security Event 4662) — the primary method for extracting token-signing certificates without reading the cert file from disk. Branch 2 monitors Azure AD Audit Logs for federation trust creation or modification, which can introduce a rogue IdP. Branch 3 detects anomalous SAML 2.0 sign-in events flagged by Azure Identity Protection with high or medium risk levels. All branches are unified and sorted by a RiskScore field for analyst prioritization.
Data Sources
Required Tables
False Positives & Tuning
- AD FS service account (computer account ending in $) legitimately reads the DKM container during token issuance — excluded by the computer account filter, but service accounts using user-format names may trigger Branch 1
- Authorized identity administrator converting a managed domain to federated during a planned AD FS deployment or migration — Branch 2 will fire; correlate with change management records
- Legitimate Identity Protection risk events on SAML-federated users traveling internationally or using VPNs — Branch 3 will fire for genuinely suspicious but non-malicious logins
- AD backup tools (e.g., Veeam, Quest Recovery Manager) performing AD object reads may access DKM container objects during full AD backups — verify backup schedules match event timing
- Entra ID Connect Health agent polling federation service health may generate benign AuditLog entries resembling federation changes
Other platforms for T1606.002
Testing Methodology
Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1AD FS DKM Container Enumeration via LDAP
Expected signal: Security Event 4662: Directory Service Object Access — SubjectUserName=<running user>, ObjectName contains 'ADFS' and 'Program Data', Properties contains GUID for thumbnailPhoto {72e39547-7b18-11d1-adef-00c04fd8d5cd}. Requires Directory Service Access auditing enabled and SACL on the DKM container. Sysmon Event 1 will show powershell.exe process creation with the LDAP query command line. Network traffic on port 389 (LDAP) from the test system to the domain controller.
- Test 2AADInternals Token-Signing Certificate Export Simulation
Expected signal: Security Event 4662: Multiple directory service access events for contact objects in the DKM container. PowerShell ScriptBlock Logging Event 4104: logs showing 'AADInternals' and 'Export-AADIntADFSCertificates'. Sysmon Event 1: powershell.exe with AADInternals command line. Sysmon Event 11 (File Create): PFX certificate files written to C:\Temp\adfs_certs_test. Windows Defender may alert on AADInternals as HackTool:PowerShell/AADInternals.
- Test 3Check Current AD FS Token-Signing Certificate Thumbprint
Expected signal: Sysmon Event 1: powershell.exe with 'Get-AdfsCertificate' and 'Token-Signing' in command line. PowerShell ScriptBlock Log Event 4104 showing certificate enumeration. AD FS Auditing Event 411 in Security log may fire indicating certificate-related administrative access. No Event 4662 expected for this test as it reads ADFS configuration via WCF, not LDAP.
- Test 4Unauthorized Federation Trust Addition Simulation (Dry Run)
Expected signal: Azure AD Audit Log entry for 'Get company information' or read-only directory query (may not generate audit event for reads). Sysmon Event 3: Network connection from powershell.exe to login.microsoftonline.com (port 443). PowerShell ScriptBlock Log Event 4104 with 'Get-MsolDomain' and 'Connect-MsolService'. Azure AD Sign-in Log for the authenticating user account connecting via MSOnline module.
References (13)
- https://attack.mitre.org/techniques/T1606/002/
- https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps
- https://www.sygnia.co/threat-reports-and-advisories/golden-saml-attack/
- https://msrc-blog.microsoft.com/2020/12/13/customer-guidance-on-recent-nation-state-cyber-attacks/
- https://blogs.microsoft.com/on-the-issues/2020/12/13/customers-protect-nation-state-cyberattacks/
- https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-configurable-token-lifetimes
- https://o365blog.com/aadkillchain/
- https://github.com/dirkjanm/adconnectdump
- https://github.com/fireeye/ADFSDump
- https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/troubleshooting/ad-fs-tshoot-logging
- https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/security-operations-privileged-accounts
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1606.002/T1606.002.md
- https://www.mandiant.com/resources/blog/remediation-and-hardening-strategies-for-microsoft-365-to-defend-against-unc2452
Unlock Pro Content
Get the full detection package for T1606.002 including response playbook, investigation guide, and atomic red team tests.