Detect Forge Web Credentials in Microsoft Sentinel
This detection identifies adversaries forging web credentials including SAML tokens, JWT assertions, AWS temporary security credentials, and session cookies by leveraging obtained secrets such as AD FS signing certificates, private keys, or application secrets. Unlike credential theft, web credential forging generates net-new authentication material that can impersonate any user and bypass MFA. Detection monitors anomalous SAML and WS-Federation authentication patterns in Azure AD sign-in logs, suspicious AWS STS API activity (AssumeRole, GetFederationToken, AssumeRoleWithSAML) from unusual principals, PowerShell and scripting process activity consistent with known token-forging frameworks such as AADInternals and Shimit (Golden SAML), federation configuration changes followed by elevated token issuance rates, and access from non-compliant or unregistered devices authenticating via federated protocols.
MITRE ATT&CK
- Tactic
- Credential Access
- Technique
- T1606 Forge Web Credentials
- Canonical reference
- https://attack.mitre.org/techniques/T1606/
KQL Detection Query
let lookback = 7d;
let saml_spike_threshold = 5;
// Detection 1: High-volume or multi-geography SAML/WS-Fed token issuance (possible forged token replay)
let SamlAnomalies = AADSignInLogs
| where TimeGenerated > ago(lookback)
| where AuthenticationProtocol in ("saml20", "wsfed", "oauthpasswordgrant")
| where ResultType == 0
| extend GeoCountry = tostring(LocationDetails.countryOrRegion)
| extend IsCompliant = tostring(DeviceDetail.isCompliant)
| extend IsManagedDevice = tostring(DeviceDetail.isManaged)
| summarize
SignInCount = count(),
UniqueIPs = dcount(IPAddress),
Countries = make_set(GeoCountry),
Apps = make_set(AppDisplayName),
IPList = make_set(IPAddress)
by UserPrincipalName, AuthenticationProtocol, IsCompliant, IsManagedDevice, bin(TimeGenerated, 1h)
| where SignInCount > saml_spike_threshold or array_length(Countries) > 2 or UniqueIPs > 3
| extend RiskScore = case(
array_length(Countries) > 3, 90,
UniqueIPs > 5, 80,
SignInCount > 20, 75,
array_length(Countries) > 1 and IsCompliant == "false", 70,
SignInCount > saml_spike_threshold, 50,
40)
| extend AlertReason = strcat(
"Suspicious SAML/federation token activity: ",
SignInCount, " sign-ins from ",
array_length(Countries), " countries, ",
UniqueIPs, " IPs")
| project TimeGenerated, UserPrincipalName, AuthenticationProtocol, SignInCount,
UniqueIPs, Countries, IPList, Apps, IsCompliant, IsManagedDevice, RiskScore, AlertReason;
// Detection 2: Federation configuration changes (pre-condition for Golden SAML)
let FedChanges = AuditLogs
| where TimeGenerated > ago(lookback)
| where OperationName in (
"Set domain authentication",
"Update domain",
"Set federation settings on domain",
"Add federated domain",
"Set DirSyncEnabled flag",
"Update StsRefreshTokensValidFrom Timestamp",
"Update authorization policy")
| extend InitiatingUser = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingApp = tostring(InitiatedBy.app.displayName)
| extend TargetResource = tostring(TargetResources[0].displayName)
| project TimeGenerated, OperationName, InitiatingUser, InitiatingApp, TargetResource, Result
| extend AlertReason = strcat("Federation configuration change: ", OperationName)
| extend RiskScore = 85;
// Detection 3: AWS STS token generation from suspicious principals (via Azure Sentinel AWS connector)
let AwsSts = CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where DeviceVendor == "Amazon Web Services"
| where Activity in ("AssumeRole", "GetFederationToken", "AssumeRoleWithSAML", "AssumeRoleWithWebIdentity")
| where DeviceAction != "NOACTION"
| extend SourcePrincipal = tostring(extract("userName=([^,]+)", 1, AdditionalExtensions))
| extend RoleArn = tostring(extract("requestRoleArn=([^,]+)", 1, AdditionalExtensions))
| where SourcePrincipal !contains "i-" and SourcePrincipal !contains "AROA" // Exclude EC2 instance profiles
| project TimeGenerated, SourceIP, SourceUserName, Activity, DeviceAddress, RoleArn, AdditionalExtensions
| extend AlertReason = strcat("Suspicious AWS STS credential generation: ", Activity)
| extend RiskScore = 75;
union SamlAnomalies, FedChanges, AwsSts
| extend TechniqueId = "T1606"
| order by RiskScore desc, TimeGenerated desc Detects three suspicious patterns consistent with web credential forging: (1) anomalous SAML/WS-Federation token issuance in Azure AD — high sign-in volume, multiple source countries, or non-compliant devices authenticating via federated protocols; (2) Azure AD federation configuration changes such as setting domain authentication or updating STS settings, which are prerequisites for Golden SAML attacks; and (3) suspicious AWS STS operations (AssumeRole, GetFederationToken, AssumeRoleWithSAML) from non-expected principals via the AWS CloudTrail connector in Microsoft Sentinel.
Data Sources
Required Tables
False Positives & Tuning
- Federated SSO environments where many users sign in via SAML simultaneously (e.g., shift start in a large org) will trigger the sign-in volume threshold — tune saml_spike_threshold per baseline
- Legitimate IT admin or privileged identity management tools that use GetFederationToken or AssumeRole for automation (AWS Lambda, CI/CD pipelines, AWS Config) will appear in the STS detection — build exclusion lists for known service principals
- Directory synchronization tools (Azure AD Connect, Okta provisioning) make federation configuration changes during scheduled sync operations and upgrades — correlate with change management records
- Security awareness or red team exercises using AADInternals or similar tooling in authorized testing windows will trigger both the federation change and SAML anomaly detections
Other platforms for T1606
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 1Golden SAML Token Forging via AADInternals
Expected signal: Sysmon Event ID 1 (Process Create) for powershell.exe with CommandLine containing 'AADInternals', 'New-AADIntSAMLToken', 'Import-Module AADInternals'. PowerShell Event ID 4104 (ScriptBlock Logging) with full decoded script content. Sysmon Event ID 7 (Image Load) for Microsoft.IdentityModel or System.IdentityModel assemblies from user profile path.
- Test 2AWS STS GetFederationToken Credential Generation
Expected signal: Sysmon Event ID 1 for aws.exe process with CommandLine containing 'get-federation-token' and 'assume-role-with-saml'. Windows Security Event 4688 (if Sysmon not available) for same process. AWS CloudTrail event: sts.amazonaws.com, eventName=GetFederationToken, sourceIPAddress of the test host.
- Test 3JWT Token Forging with Algorithm Confusion (None Algorithm)
Expected signal: Sysmon Event ID 1 (Linux: auditd execve) for python3 process with CommandLine containing 'none', 'algorithm', 'jwt', 'forge'. Linux syslog records python3 invocation. Process arguments visible in /proc/<pid>/cmdline during execution.
- Test 4Zimbra Pre-Authentication Key Generation (T1606 Variant)
Expected signal: Sysmon Event ID 1 for bash and python3 processes with CommandLine containing 'zmprov', 'gdpak', 'zimbra', 'preauth'. Linux auditd EXECVE records for bash -c with zmprov pattern. /tmp/zimbra_preauth_test.txt file creation event.
References (7)
- https://attack.mitre.org/techniques/T1606/
- https://attack.mitre.org/techniques/T1606/001/
- https://attack.mitre.org/techniques/T1606/002/
- https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-sign-ins
- https://www.mandiant.com/resources/blog/detecting-and-responding-to-adfs-attacks
- https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithSAML.html
- https://wiki.zimbra.com/wiki/Preauth
Unlock Pro Content
Get the full detection package for T1606 including response playbook, investigation guide, and atomic red team tests.