Detect Forge Web Credentials in Splunk
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/
SPL Detection Query
index=* (sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" OR sourcetype="WinEventLog:Security")
| eval EventCode=coalesce(EventCode, event_id)
| search EventCode IN ("1", "4688")
| eval process_name=lower(coalesce(Image, NewProcessName, ""))
| eval command_line=coalesce(CommandLine, ProcessCommandLine, "")
| eval parent_process=lower(coalesce(ParentImage, ParentProcessName, ""))
| eval user=coalesce(User, SubjectUserName, "")
| eval hostname=coalesce(Computer, host)
| eval ts=strftime(_time, "%Y-%m-%d %H:%M:%S")
| eval risk_score=0
`comment("--- Credential forging framework detection ---")`
| eval risk_score=risk_score + if(match(command_line, "(?i)(AADInternals|Open-AzureOffice365Connection|ConvertTo-AADToken|Get-AADIntAccessToken|New-AADIntSAMLToken)"), 70, 0)
| eval risk_score=risk_score + if(match(command_line, "(?i)(golden[_\-\s]saml|shimit|ADFSpoof|samlReplay|Invoke-ADFSTokenSigning)"), 80, 0)
| eval risk_score=risk_score + if(match(command_line, "(?i)(Get-ADFSProperties|Export-PfxCertificate.*ADFS|Get-ADFSCertificate)"), 50, 0)
`comment("--- AWS STS credential forging via CLI ---")`
| eval risk_score=risk_score + if(match(command_line, "(?i)sts.*(assume-role-with-saml|get-federation-token|assume-role-with-web-identity)"), 60, 0)
`comment("--- Zimbra preauth key abuse ---")`
| eval risk_score=risk_score + if(match(command_line, "(?i)zmprov.*gdpak|zimbra.*preauth"), 55, 0)
`comment("--- JWT forgery patterns ---")`
| eval risk_score=risk_score + if(match(command_line, "(?i)(jwt.*forge|sign.*jwt|HS256.*secret|RS256.*privkey|none.*algorithm)"), 50, 0)
`comment("--- Suspicious parent process context ---")`
| eval risk_score=risk_score + if(match(process_name, "(?i)(powershell|pwsh)") AND match(parent_process, "(?i)(winword|excel|outlook|chrome|firefox|msedge)"), 25, 0)
| where risk_score >= 40
| eval detection_reason=case(
match(command_line, "(?i)(AADInternals|golden[_\-\s]saml|ADFSpoof|samlReplay)"), "Known credential forging tool invocation",
match(command_line, "(?i)Get-ADFSCertificate|Export-PfxCertificate.*ADFS"), "AD FS certificate extraction attempt",
match(command_line, "(?i)sts.*(assume-role-with-saml|get-federation-token)"), "AWS STS federation token generation",
match(command_line, "(?i)zmprov.*gdpak"), "Zimbra preauth key generation",
1==1, "Credential forging behavioral pattern")
| stats count as event_count,
max(risk_score) as max_risk,
values(command_line) as command_lines,
values(process_name) as processes,
values(parent_process) as parent_processes,
values(detection_reason) as reasons
by hostname, user
| where max_risk >= 40
| eval severity=case(max_risk >= 70, "Critical", max_risk >= 50, "High", "Medium")
| sort - max_risk
| table hostname, user, severity, max_risk, event_count, reasons, processes, command_lines, parent_processes Detects process creation events on Windows hosts consistent with web credential forging activity: invocation of known tools such as AADInternals PowerShell module (Open-AzureOffice365Connection, New-AADIntSAMLToken), Golden SAML frameworks (Shimit, ADFSpoof), AD FS certificate extraction commands, AWS CLI STS federation token requests, Zimbra preauth key generation (zmprov gdpak), and JWT algorithm manipulation patterns. Events are scored by risk tier and grouped by host and user to surface compound credential forging sequences.
Data Sources
Required Sourcetypes
False Positives & Tuning
- Security teams using AADInternals legitimately for Azure AD administration, auditing, or authorized penetration testing — add authorized host/user exclusions to the risk scoring block
- AWS CLI usage of assume-role in DevOps pipelines, CI/CD automation, and cloud engineers rotating credentials — build an exclusion list of known automation service accounts
- JWT library testing and development activity using Python or Node.js JWT packages on developer workstations — exclude development hosts by hostname prefix or subnet
- AD FS certificate exports during scheduled PKI certificate renewals or disaster recovery procedures — correlate with change management tickets and maintenance windows
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 1 Golden 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 2 AWS 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 3 JWT 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 4 Zimbra 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
Response Playbook
Triage
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
- 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.
- 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.
- 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.
- Isolate the source host identified in process-based detections using EDR quarantine or network segmentation. Do not power off — preserve volatile memory.
- 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.
- Block the offending source IPs identified in AADSignInLogs at the perimeter or Conditional Access policy level.
Evidence Collection
- Export full AADSignInLogs for the affected user spanning 7 days before and after alert. Focus on AuthenticationProtocol, IPAddress, LocationDetails, DeviceDetail, and ConditionalAccessStatus fields.
- Collect AuditLogs for all federation and authentication policy changes over the past 30 days. Export to CSV for offline analysis.
- 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\
- 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.
- 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.
- 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.
- 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
Related Techniques
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.
// 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 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.
// 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 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.
// 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 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
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
# 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
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.
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
# 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
# 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.
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
#!/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
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.
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
#!/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}×tamp={ts}&expires={expires}&preauth={hmac_val}')
"
echo '[*] Detection test complete' Cleanup
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'.