T1606

Forge Web Credentials

Credential Access Last updated:

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.

What is T1606 Forge Web Credentials?

Forge Web Credentials (T1606) maps to the Credential Access tactic — the adversary is trying to steal account names and passwords in MITRE ATT&CK.

This page provides production-ready detection logic for Forge Web Credentials, covering the data sources and telemetry it touches: Azure Active Directory, Microsoft Entra ID, AWS CloudTrail via Sentinel Connector. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Credential Access
Technique
T1606 Forge Web Credentials
Canonical reference
https://attack.mitre.org/techniques/T1606/
Microsoft Sentinel / Defender
kusto
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.

high severity medium confidence

Data Sources

Azure Active Directory Microsoft Entra ID AWS CloudTrail via Sentinel Connector

Required Tables

AADSignInLogs AuditLogs CommonSecurityLog

False Positives

  • 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

Sigma rule & cross-platform mapping

The detection logic for Forge Web Credentials (T1606) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  product: azure

Browse the community-maintained Sigma rules for this technique:


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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.


Response Playbook

Triage

  1. Step 1: Identify the alert type. Determine which detection branch fired — federation config change, anomalous SAML sign-in volume, AWS STS abuse, or process-based tool detection. Each branch has a different investigation path.
  2. Step 2 (SAML volume anomaly): Pull the full AADSignInLogs for the flagged UserPrincipalName over the past 24h. Check whether the sign-ins originate from a single IP/ASN or genuinely distributed locations. A single IP with high volume suggests token replay; multiple IPs suggest credential stuffing or forged token distribution.
  3. Step 3 (Federation config change): Query AuditLogs for InitiatingUser and correlate with HR/IT provisioning systems. Check if a change management ticket exists. Retrieve the previous and new federation settings using Graph API or Azure Portal to determine if a signing certificate was replaced or a new IdP was added.
  4. Step 4 (Process-based): Examine the full process tree for the flagged event. Pull parent/child process relationships from Sysmon Event ID 1 logs. Determine whether PowerShell was launched from an Office application, browser, or remote management tool — these suggest initial access rather than insider threat.
  5. Step 5: Check for lateral movement indicators. Query DeviceLogonEvents and SecurityEvent (4624, 4648) for the flagged user/host in the ±2h window around the alert. Look for authentication events targeting privileged systems, admin shares, or service accounts.
  6. Step 6: Verify account status in Azure AD. Check LastSignInDateTime, MFA registration status, registered devices, and recent password changes. A forged token does not require the victim's password, so absence of password reset is not reassurance — focus on session activity.
  7. Step 7 (AWS STS): Pull CloudTrail logs for the source principal's AssumeRole activity. Verify the RoleArn that was assumed — does it grant admin, data access, or cross-account trust? Check if the assumed role was used to access S3, Secrets Manager, or IAM after the token was generated.

Containment

  1. For suspected Golden SAML (AD FS compromise): Immediately revoke all outstanding federation tokens by updating the ImmutableID or rotating the AD FS token-signing certificate. In Azure AD, run: Update-MSOLFederatedDomain -DomainName <domain> -SupportMultipleDomain. This invalidates all tokens signed with the old certificate.
  2. For Azure AD SAML abuse: Use the Azure AD Portal or PowerShell (Revoke-AzureADUserAllRefreshToken -ObjectId <UPN>) to revoke all refresh tokens for affected users. This forces re-authentication.
  3. For AWS STS token abuse: Call iam:DeleteAccessKey or sts:RevokeAccessKey for the source principal. For assumed-role sessions, there is no direct revocation — update the trust policy to deny the compromised principal, or delete and recreate the IAM role.
  4. Isolate the source host identified in process-based detections using EDR quarantine or network segmentation. Do not power off — preserve volatile memory.
  5. For Zimbra preauth abuse: Rotate the preauth secret immediately using: zmprov md <domain> zimbraPreAuthKey $(zmjava com.zimbra.cs.account.PreAuthKey). All previously generated preauth tokens become invalid.
  6. Block the offending source IPs identified in AADSignInLogs at the perimeter or Conditional Access policy level.

Evidence Collection

  1. Export full AADSignInLogs for the affected user spanning 7 days before and after alert. Focus on AuthenticationProtocol, IPAddress, LocationDetails, DeviceDetail, and ConditionalAccessStatus fields.
  2. Collect AuditLogs for all federation and authentication policy changes over the past 30 days. Export to CSV for offline analysis.
  3. On the suspect host: collect the PowerShell ScriptBlock logs (Event ID 4104 from Microsoft-Windows-PowerShell/Operational), module load events, and transcript files if enabled. Path: C:\Users\<user>\Documents\PowerShell\Transcripts\
  4. Dump the running process memory of any flagged PowerShell or scripting processes before quarantine using ProcDump or EDR memory acquisition — forged token material may be in memory.
  5. Collect AD FS event logs from federation servers: Applications and Services Logs > AD FS > Admin (Event IDs 411, 510, 1007). These record token issuance and validation failures.
  6. For AWS: export CloudTrail events for the source principal for the past 7 days including all management events. Focus on sts:*, iam:*, and s3:GetObject events following the suspicious AssumeRole call.
  7. If AD FS servers are in scope, collect the DKM (Distributed Key Manager) container permissions and AD FS service account activity from the AD security audit logs.

Escalation Criteria

  • ! Escalate immediately if the federation configuration change was performed by a non-human service account or an account with no prior administrative activity — strongly suggests compromised privileged account used for setup.
  • ! Escalate if Golden SAML tooling (AADInternals, ADFSpoof, Shimit) was found on a system that is not part of the authorized security testing program — this is an active intrusion.
  • ! Escalate if forged credentials were used to access privileged resources: Global Administrator roles, AWS root account, S3 buckets with sensitive data, Secret Manager, Key Vault, or domain controllers.
  • ! Escalate if the affected user's account shows sign-in activity from a country inconsistent with their employment location or travel history, especially if MFA was satisfied via SAML (no step-up prompt).
  • ! Escalate if the AWS assumed role has cross-account trust relationships — forged temporary credentials could have propagated to partner or customer AWS environments.
  • ! Escalate if evidence of data staging or exfiltration (T1074, T1567) is detected within 4 hours of the forged credential activity.

Investigation Guide

Forensic Artifacts

  • > PowerShell ScriptBlock logs (Event ID 4104): Contains decoded script content including AADInternals module commands, JWT manipulation, and credential forging logic
  • > AD FS event logs (Applications and Services Logs > AD FS > Admin): Event IDs 510 (token issuance), 1007 (token validation failure), 411 (no active endpoint) record federation token activity
  • > Azure AD Sign-In Logs: AuthenticationProtocol, TokenIssuerType, and ConditionalAccessStatus fields reveal SAML vs. password authentication and policy bypass
  • > AWS CloudTrail: sts:AssumeRole, sts:AssumeRoleWithSAML, sts:GetFederationToken events with sourceIPAddress, userAgent, and requestParameters.roleArn
  • > Memory forensics: Token material, signing keys, and AADInternals session objects may persist in PowerShell process memory — collect with ProcDump before host isolation
  • > C:\Windows\ADFS\Config\Microsoft.IdentityServer.servicehost.exe.config — contains token signing certificate thumbprints for comparison
  • > HKLM\SOFTWARE\Microsoft\ADFS — registry keys may be modified by forging tools to alter token behavior
  • > Prefetch files: C:\Windows\Prefetch\POWERSHELL.EXE-*.pf — timestamps confirm when PowerShell was executed even if logs were cleared
  • > Browser credential stores (if web cookies targeted): %LOCALAPPDATA%\Google\Chrome\User Data\Default\Cookies, %APPDATA%\Mozilla\Firefox\Profiles\*.default\cookies.sqlite

Tuning Guidance

The SAML sign-in volume threshold (saml_spike_threshold = 5) should be calibrated to your organization's normal federation baseline — large enterprises may see hundreds of SAML sign-ins per hour per user during shift start. Use a 14-day baseline period to compute per-user SAML hourly averages and replace the static threshold with a dynamic anomaly (e.g., current_count > avg + 3*stdev). The process-based SPL detection uses tool-name matching — update the AADInternals module names list as the toolset evolves. For the AWS STS detection, build a dynamic exclusion list of known automation service accounts by running a 30-day frequency analysis on principals calling sts:AssumeRole and excluding those appearing in >80% of days. The federation config change detection has very low false positive rate and should not require significant tuning — every alert should be reviewed against change management records.


Hunting Queries

Hunt for SAML/WS-Fed tokens issued without Conditional Access enforcement or MFA, which may indicate forged tokens bypassing policy controls. Forged SAML assertions crafted outside the normal IdP flow often lack the claims required to satisfy Conditional Access policies, or are used in contexts where CA was not applied.

Hunting — KQL
kql
// Hunt: Unusual token issuance to cloud apps from non-MFA-compliant sessions
AADSignInLogs
| where TimeGenerated > ago(30d)
| where ResultType == 0
| where AuthenticationProtocol in ("saml20", "wsfed")
| extend MfaSatisfied = tostring(AuthenticationDetails[0].succeeded)
| extend ConditionalAccessResult = ConditionalAccessStatus
| where ConditionalAccessResult in ("notApplied", "notEnabled") or MfaSatisfied == "false"
| extend AppCategory = case(
    AppDisplayName has_any ("Exchange", "SharePoint", "Teams"), "Microsoft 365",
    AppDisplayName has_any ("AWS", "Amazon"), "AWS",
    AppDisplayName has_any ("Salesforce", "ServiceNow", "Workday"), "SaaS",
    "Other")
| where AppCategory != "Other"
| summarize
    TokensIssued = count(),
    UniqueApps = dcount(AppDisplayName),
    IPAddresses = make_set(IPAddress),
    AppList = make_set(AppDisplayName)
    by UserPrincipalName, AppCategory, ConditionalAccessResult, bin(TimeGenerated, 24h)
| where TokensIssued > 3
| order by TokensIssued desc
Hunting — SPL
spl
index=* sourcetype="o365:management:activity" OR sourcetype="azure:aad:signin"
| eval auth_protocol=coalesce(AuthenticationProtocol, auth_protocol)
| search auth_protocol IN ("saml20", "wsfed", "wsFed")
| eval result=coalesce(ResultType, ResultDescription)
| where result="0" OR result="Success"
| eval conditional_access=coalesce(ConditionalAccessStatus, "notApplied")
| where conditional_access IN ("notApplied", "notEnabled", "failure")
| eval app=coalesce(AppDisplayName, ApplicationId)
| stats count as token_count, dc(IPAddress) as unique_ips, values(app) as apps by UserPrincipalName, conditional_access, span(_time, 1d)
| where token_count > 3
| sort - token_count

Hunts for elevated Kerberos service ticket requests targeting AD FS service principal names and federation endpoints, and correlates Azure AD sign-in volume spikes following federation configuration changes. A sudden increase in SAML sign-ins after an AD FS configuration change may indicate the configuration was modified to enable token forging.

Hunting — KQL
kql
// Hunt: AD FS or federation service configuration changes followed by new user sign-in patterns
let FedChangeTime = AuditLogs
| where TimeGenerated > ago(90d)
| where OperationName in ("Set domain authentication", "Update domain", "Set federation settings on domain")
| summarize LastChange = max(TimeGenerated) by OperationName
| summarize LatestFedChange = max(LastChange);
AADSignInLogs
| where TimeGenerated > ago(30d)
| where AuthenticationProtocol in ("saml20", "wsfed")
| where ResultType == 0
| join kind=inner (FedChangeTime) on $left.TimeGenerated > $right.LatestFedChange
| extend GeoCountry = tostring(LocationDetails.countryOrRegion)
| summarize
    NewSignIns = count(),
    UniqueUsers = dcount(UserPrincipalName),
    Countries = make_set(GeoCountry)
    by AppDisplayName, AuthenticationProtocol, bin(TimeGenerated, 1h)
| where NewSignIns > 10 or array_length(Countries) > 3
| order by NewSignIns desc
Hunting — SPL
spl
index=* sourcetype="WinEventLog:Security" EventCode=4769
| eval spn=ServiceName
| where match(spn, "(?i)ADFS|federation|saml|sso")
| eval requesting_user=TargetUserName
| eval service_host=ServiceSid
| eval ticket_options=TicketOptions
| eval encryption_type=TicketEncryptionType
| where encryption_type IN ("0x12", "0x11") OR encryption_type!="0x17"
| stats count as ticket_count, dc(requesting_user) as unique_requestors, values(requesting_user) as users by spn, _time span=1h
| where ticket_count > 20 OR unique_requestors > 5
| sort - ticket_count
| table _time, spn, ticket_count, unique_requestors, users

Hunts for scripting runtimes (PowerShell, Python, Node.js) loading identity and authentication libraries (Microsoft.IdentityServer, System.IdentityModel, AADInternals) from non-standard paths. Legitimate AD FS administration loads these from system assembly cache; credential forging tools load them from user-writable locations such as Downloads, Temp, or module staging directories.

Hunting — KQL
kql
// Hunt: PowerShell loading AD FS, ADAL, or MSAL assemblies from unusual paths
DeviceImageLoadEvents
| where TimeGenerated > ago(30d)
| where InitiatingProcessFileName in~ ("powershell.exe", "pwsh.exe", "python.exe", "ruby.exe", "node.exe")
| where FileName has_any (
    "Microsoft.IdentityServer",
    "Microsoft.IdentityModel",
    "AADInternals",
    "ADAL",
    "MSAL",
    "System.IdentityModel",
    "jose",
    "jwt")
| where not(FolderPath has_any (
    "C:\\Windows\\assembly",
    "C:\\Program Files\\WindowsPowerShell\\Modules\\Az",
    "C:\\Program Files\\WindowsPowerShell\\Modules\\AzureAD",
    "C:\\Program Files (x86)\\Microsoft SDKs"))
| summarize
    LoadCount = count(),
    LoadedLibraries = make_set(FileName),
    LoadPaths = make_set(FolderPath)
    by DeviceName, InitiatingProcessAccountName, InitiatingProcessCommandLine, bin(TimeGenerated, 1h)
| where LoadCount > 0
| order by LoadCount desc
Hunting — SPL
spl
index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=7
| eval image_loaded=lower(ImageLoaded)
| eval initiating_process=lower(Image)
| search image_loaded IN ("*microsoft.identityserver*", "*microsoft.identitymodel*", "*aadinternals*", "*system.identitymodel*")
| search initiating_process IN ("*powershell.exe", "*pwsh.exe", "*python.exe", "*node.exe")
| where NOT match(image_loaded, "c:\\\\windows\\\\assembly|c:\\\\program files\\\\windowspowershell\\\\modules\\\\az")
| stats count as load_count, values(image_loaded) as libraries, values(ImageLoaded) as full_paths by Computer, User, Image
| where load_count > 0
| sort - load_count
| table Computer, User, Image, load_count, libraries, full_paths

Atomic Red Team Tests

Test 1 Golden SAML Token Forging via AADInternals
windows

Simulates a Golden SAML attack by using the AADInternals PowerShell module to forge a SAML token for an arbitrary Azure AD user. Requires a previously exported AD FS token-signing certificate (PFX). This test validates detection of AADInternals module invocation and SAML assertion generation.

Command

powershell
# Step 1: Install AADInternals (if not present)
Install-Module AADInternals -Scope CurrentUser -Force
Import-Module AADInternals

# Step 2: Simulate loading a test signing certificate (use a self-signed cert for safe testing)
$cert = New-SelfSignedCertificate -Subject 'CN=ADFS-Test-Signing' -KeyAlgorithm RSA -KeyLength 2048 -CertStoreLocation 'Cert:\CurrentUser\My' -NotAfter (Get-Date).AddYears(1)
$certThumbprint = $cert.Thumbprint
Write-Host "Test cert thumbprint: $certThumbprint"

# Step 3: Invoke SAML token generation function (uses test cert — no actual AD FS access)
# This generates the same process telemetry as a real attack without valid credentials
try {
    $samlAssertion = New-AADIntSAMLToken -UPN '[email protected]' -ImmutableID 'AAAA1234' -Issuer 'http://adfs.test.local/adfs/services/trust' -PfxFileName "$env:TEMP\test-adfs.pfx" -PfxPassword 'TestPass123!'
    Write-Host "SAML token generated (test mode)"
} catch {
    Write-Host "Expected error in test environment: $($_.Exception.Message)"
    Write-Host "Process telemetry generated for detection validation"
}

Cleanup

powershell
Remove-Module AADInternals -Force -ErrorAction SilentlyContinue
Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Subject -eq 'CN=ADFS-Test-Signing'} | Remove-Item

Expected Telemetry

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.

Expected Detection

SPL detection fires on risk_score >= 70 due to AADInternals pattern match. Alert reason: 'Known credential forging tool invocation' with process powershell.exe.

Test 2 AWS STS GetFederationToken Credential Generation
windows

Simulates an adversary using AWS STS GetFederationToken to generate temporary federated credentials that can be used to impersonate a user. Requires AWS CLI configured with valid IAM credentials. Tests AWS STS telemetry detection via CloudTrail.

Command

powershell
# Prerequisites: AWS CLI installed, credentials configured with sts:GetFederationToken permission
# This uses real AWS APIs but generates credentials for a test policy only

# Step 1: Verify AWS CLI is configured
aws sts get-caller-identity

# Step 2: Generate federated token with minimal test policy
$testPolicy = '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["s3:ListBucket"],"Resource":"*"}]}'
aws sts get-federation-token `
    --name 'argus-detection-test' `
    --duration-seconds 900 `
    --policy $testPolicy `
    --output json

# Step 3: Simulate AssumeRoleWithSAML pattern (dry-run — no valid SAML assertion)
# This generates the CLI invocation telemetry
try {
    aws sts assume-role-with-saml `
        --role-arn 'arn:aws:iam::123456789012:role/TestDetectionRole' `
        --principal-arn 'arn:aws:iam::123456789012:saml-provider/TestIdP' `
        --saml-assertion 'INVALID_SAML_FOR_TESTING' 2>&1 | Write-Host
} catch {
    Write-Host "Expected error — CLI telemetry generated: $($_.Exception.Message)"
}

Cleanup

powershell
# Federated tokens expire automatically after --duration-seconds
# No persistent resources created
Write-Host 'Cleanup complete — temporary credentials will expire automatically'

Expected Telemetry

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.

Expected Detection

SPL detection fires on risk_score >= 60 due to AWS STS pattern match. KQL CommonSecurityLog alert fires for AssumeRoleWithSAML or GetFederationToken activity from unexpected principal.

Test 3 JWT Token Forging with Algorithm Confusion (None Algorithm)
linux

Simulates JWT credential forging using the 'none' algorithm attack, where an adversary removes the signature from a JWT token, changes the algorithm to 'none', and submits it to a vulnerable application. Uses Python to craft the forged token and validates detection of JWT manipulation patterns in process telemetry.

Command

bash
#!/bin/bash
# Step 1: Install PyJWT for test
pip3 install PyJWT requests --quiet 2>/dev/null || pip install PyJWT requests --quiet

# Step 2: Craft a JWT with 'none' algorithm (simulates algorithm confusion attack)
python3 - <<'EOF'
import base64
import json
import sys

def b64url_encode(data):
    if isinstance(data, str):
        data = data.encode()
    return base64.urlsafe_b64encode(data).rstrip(b'=').decode()

# Forge a JWT with 'none' algorithm - no signature validation bypass
header = {"alg": "none", "typ": "JWT"}
payload = {
    "sub": "[email protected]",
    "name": "Forged Admin Token",
    "admin": True,
    "iat": 1700000000,
    "exp": 9999999999,
    "roles": ["GlobalAdministrator"]
}

forged_token = f"{b64url_encode(json.dumps(header))}.{b64url_encode(json.dumps(payload))}."
print(f"[+] Forged JWT (none algorithm): {forged_token}")
print(f"[+] Decoded header: {header}")
print(f"[+] Decoded payload: {payload}")
print("[*] Detection test complete - process telemetry generated")
EOF

# Step 3: Simulate HS256->RS256 confusion (common JWT attack pattern)
python3 -c "
import subprocess
print('[*] Simulating JWT algorithm confusion attack telemetry')
print('[*] Command: python3 -c none algorithm jwt forge RS256 privkey')
"

Cleanup

bash
pip3 uninstall PyJWT -y --quiet 2>/dev/null || true
echo 'Cleanup complete'

Expected Telemetry

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.

Expected Detection

SPL detection fires on risk_score >= 50 due to JWT forgery pattern match ('none.*algorithm', 'jwt.*forge') in command_line field. Alert severity: Medium.

Test 4 Zimbra Pre-Authentication Key Generation (T1606 Variant)
linux

Simulates the Zimbra zmprov gdpak command used to generate a pre-authentication key that enables token forging for any user in the domain. This is a T1606 variant targeting on-premises Zimbra mail servers. The test generates expected command-line telemetry without requiring an actual Zimbra installation.

Command

bash
#!/bin/bash
# Simulate zmprov gdpak command invocation for detection testing
# This does NOT require a Zimbra installation — generates the process telemetry pattern

echo '[*] Simulating Zimbra preauth key generation command (detection test)'

# Create a wrapper that mimics the command signature
bash -c 'echo Simulating: zmprov gdpak domain.com preauth'

# Execute the actual command pattern that detection rules look for
# (safe simulation - /usr/bin/zmprov will not exist, but process telemetry is generated)
echo 'zmprov gdpak test.local' | tee /tmp/zimbra_preauth_test.txt

# Simulate the token generation that would follow
python3 -c "
import hashlib, hmac, time
preauth_key = 'SIMULATED_PREAUTH_KEY_FOR_DETECTION_TESTING'
user = '[email protected]'
ts = str(int(time.time()) * 1000)
by = 'id'
expires = '0'
hmac_val = hmac.new(preauth_key.encode(), f'{user}|{by}|{expires}|{ts}'.encode(), hashlib.sha1).hexdigest()
print(f'[+] Simulated Zimbra preauth HMAC: {hmac_val}')
print(f'[+] Would URL: /service/preauth?account={user}&by={by}&timestamp={ts}&expires={expires}&preauth={hmac_val}')
"

echo '[*] Detection test complete'

Cleanup

bash
rm -f /tmp/zimbra_preauth_test.txt

Expected Telemetry

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.

Expected Detection

SPL detection fires on risk_score >= 55 due to Zimbra preauth pattern match ('zmprov.*gdpak', 'zimbra.*preauth'). Alert reason: 'Zimbra preauth key generation'.

Related Detections