Detect Steal Application Access Token in IBM QRadar
Adversaries may steal application access tokens as a means of acquiring credentials to access remote systems and resources. Application access tokens — including OAuth 2.0 tokens, Kubernetes service account tokens, cloud provider temporary credentials (Azure Managed Identity via IMDS, AWS STS instance role credentials, GCP service account tokens), and CI/CD pipeline secrets — authorize API requests on behalf of users or services. Token theft enables adversaries to impersonate legitimate identities, access cloud resources and SaaS platforms with the victim's permissions, and move laterally without requiring plaintext passwords. Real-world examples include APT29 stealing OAuth tokens via malicious application consent phishing, APT28 creating fraudulent OAuth apps masquerading as Google services, and threat actors exploiting compromised containers to extract Kubernetes service account tokens via the pod filesystem.
MITRE ATT&CK
- Tactic
- Credential Access
- Technique
- T1528 Steal Application Access Token
- Canonical reference
- https://attack.mitre.org/techniques/T1528/
QRadar Detection Query
SELECT
DATEFORMAT(starttime, 'YYYY-MM-dd HH:mm:ss') AS EventTime,
sourceip AS SourceIP,
destinationip AS DestinationIP,
username AS Actor,
"Application" AS ProcessName,
"URL" AS RequestURL,
"fileName" AS FileName,
"filePath" AS FilePath,
CATEGORYNAME(category) AS EventCategory,
LOGSOURCETYPENAME(devicetype) AS LogSourceType,
UTF8(payload) AS RawEvent,
CASE
WHEN destinationip = '169.254.169.254'
AND (
"URL" IMATCHES '.*metadata/identity.*'
OR "URL" IMATCHES '.*iam/security-credentials.*'
OR "URL" IMATCHES '.*computeMetadata/v1/instance/service-accounts.*'
OR "URL" IMATCHES '.*metadata/instance.*'
)
THEN 'IMDS Token Request'
WHEN "filePath" IMATCHES '.*(kubernetes\.io/serviceaccount|run/secrets/kubernetes|run/secrets/tokens).*'
THEN 'Kubernetes Service Account Token'
WHEN
"fileName" IMATCHES '.*(msal_token_cache|accessTokens\.json|application_default_credentials|azureProfile\.json|\.git-credentials|TokenCache\.dat).*'
OR ("filePath" IMATCHES '.*\.config/gcloud.*' AND "fileName" IMATCHES '.*\.json')
OR ("filePath" IMATCHES '.*\.azure.*' AND "fileName" IMATCHES '.*\.json')
THEN 'OAuth Token Cache Access'
WHEN
CATEGORYNAME(category) IMATCHES '.*(application consent|OAuth consent|permission grant).*'
AND UTF8(payload) IMATCHES '.*(Mail\.ReadWrite|Files\.ReadWrite\.All|User\.Read\.All|Directory\.ReadWrite\.All|offline_access|full_access_as_user|EWS\.AccessAsUser\.All).*'
THEN 'OAuth High-Privilege Consent Grant'
ELSE NULL
END AS Vector,
CASE
WHEN destinationip = '169.254.169.254' AND "URL" IMATCHES '.*metadata/identity.*' THEN 'Azure Managed Identity'
WHEN destinationip = '169.254.169.254' AND "URL" IMATCHES '.*iam/security-credentials.*' THEN 'AWS Instance Role'
WHEN destinationip = '169.254.169.254' AND "URL" IMATCHES '.*service-accounts.*' THEN 'GCP Service Account'
WHEN "filePath" IMATCHES '.*kubernetes.*' THEN 'Kubernetes'
WHEN "fileName" IMATCHES '.*msal.*' OR "filePath" IMATCHES '.*\.azure.*' THEN 'Azure'
WHEN "filePath" IMATCHES '.*\.config/gcloud.*' OR "fileName" IMATCHES '.*application_default.*' THEN 'GCP'
WHEN "fileName" IMATCHES '.*\.git-credentials.*' THEN 'GitHub/Git'
ELSE 'Multi-Cloud'
END AS TokenPlatform
FROM events
WHERE
starttime > NOW() - 86400000
AND (
-- Vector 1: IMDS token requests from non-native processes
(
destinationip = '169.254.169.254'
AND (
"URL" IMATCHES '.*metadata/identity.*'
OR "URL" IMATCHES '.*iam/security-credentials.*'
OR "URL" IMATCHES '.*computeMetadata/v1/instance/service-accounts.*'
OR "URL" IMATCHES '.*metadata/instance.*'
)
AND NOT "Application" IMATCHES '.*(waagent|WindowsAzureGuestAgent|WaAppAgent|MonAgentCore|HealthService|MMAExtensionHeartbeatService|AzureAttestService|azd\.exe|AzureCLI).*'
)
OR
-- Vector 2: Kubernetes service account token file reads
(
"filePath" IMATCHES '.*(kubernetes\.io/serviceaccount|run/secrets/kubernetes\.io|var/run/secrets/tokens).*'
AND "fileName" IN ('token', 'ca.crt')
AND NOT "Application" IMATCHES '.*(kubelet|pause|containerd-shim|containerd-shim-runc-v2|runc|cri-o|dockerd).*'
)
OR
-- Vector 3: OAuth and cloud CLI token cache file access
(
(
"fileName" IMATCHES '.*(msal_token_cache|accessTokens\.json|application_default_credentials|azureProfile\.json|\.git-credentials|TokenCache\.dat).*'
OR ("filePath" IMATCHES '.*\.config/gcloud.*' AND "fileName" IMATCHES '.*\.json')
OR ("filePath" IMATCHES '.*\.azure.*' AND "fileName" IMATCHES '.*\.json')
)
AND NOT "Application" IMATCHES '.*(gcloud(\.exe)?|aws(\.exe)?|\baz(\.exe)?|gh(\.exe)?|\bgit(\.exe)?|terraform(\.exe)?|kubectl(\.exe)?|Code\.exe).*'
)
OR
-- Vector 4: High-privilege OAuth consent grants
(
CATEGORYNAME(category) IMATCHES '.*(application consent|OAuth consent|permission grant).*'
AND UTF8(payload) IMATCHES '.*(Mail\.ReadWrite|Files\.ReadWrite\.All|User\.Read\.All|Directory\.ReadWrite\.All|offline_access|full_access_as_user|EWS\.AccessAsUser\.All).*'
)
)
ORDER BY starttime DESC Detects T1528 application access token theft in IBM QRadar AQL across four vectors: (1) HTTP connections to the cloud IMDS IP 169.254.169.254 from processes not in the native agent allowlist, targeting credential-bearing URL paths; (2) file system reads of Kubernetes service account tokens by non-orchestration processes; (3) access to OAuth and cloud CLI token cache files by untrusted processes; and (4) high-privilege OAuth application consent events with sensitive Microsoft 365 permission scopes detected via payload inspection. Requires QRadar Custom Event Properties mapped from endpoint EDR, Sysmon, and cloud audit log sources to populate Application, URL, fileName, and filePath fields. The IMATCHES operator performs case-insensitive regex matching. NOW() returns epoch milliseconds; 86400000 = 24 hours.
Data Sources
Required Tables
False Positives & Tuning
- Azure VM Agent, AWS SSM Agent, and GCP OS Config daemon legitimately poll IMDS on a scheduled interval — the Application IMATCHES exclusion must be tuned to include all cloud platform native agent binary names and paths present in your environment
- CI/CD pipelines executing cloud deployments in containers frequently read Kubernetes service account tokens for cluster API authentication — correlate with known pipeline runner hostnames, service account names, and job execution windows
- Automated infrastructure management tools (Ansible, Terraform Cloud agent, Chef) may access cloud credential files as part of environment bootstrapping — validate against scheduled maintenance windows and approved automation service accounts before escalating
Other platforms for T1528
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 1Query Azure IMDS Endpoint for Managed Identity Token
Expected signal: Sysmon Event ID 3: Network Connection from powershell.exe to 169.254.169.254:80. DeviceNetworkEvents in MDE: RemoteIP=169.254.169.254, InitiatingProcessFileName=powershell.exe. The RemoteUrl field will contain the metadata identity path.
- Test 2Read Kubernetes Service Account Token from Pod Filesystem
Expected signal: Linux auditd syscall audit event for openat/read on /var/run/secrets/kubernetes.io/serviceaccount/token with the process name (cat or the shell). Sysmon for Linux Event ID 11 (if deployed) for file access. The token value (JWT) will be visible in any memory or command output capture.
- Test 3Enumerate and Exfiltrate Azure CLI Token Cache
Expected signal: Sysmon Event ID 11: File access/creation event with TargetFilename matching *msal_token_cache.json and Image=powershell.exe. DeviceFileEvents in MDE: FileName=msal_token_cache.json, ActionType=FileRead or FileAccessed, InitiatingProcessFileName=powershell.exe.
- Test 4Register Malicious OAuth App and Simulate Consent Phishing Link
Expected signal: Azure AD AuditLogs OperationName='Add application' followed by 'Update application' with permissions modification. The registered app will appear in AuditLogs with the requesting user's UPN and source IP. If a test user clicks the generated consent URL, AuditLogs will show OperationName='Consent to application' with the scopes granted.
References (13)
- https://attack.mitre.org/techniques/T1528/
- https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token
- https://posts.specterops.io/managed-identity-attack-paths-part-1-automation-accounts-82667d17187a
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
- https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
- https://www.amnesty.org/en/latest/research/2019/08/evolving-phishing-attacks-targeting-journalists-and-human-rights-defenders-from-the-middle-east-and-north-africa/
- https://blog.trendmicro.com/trendlabs-security-intelligence/pawn-storm-abuses-open-authentication-advanced-social-engineering-attacks
- https://auth0.com/blog/why-should-use-accesstokens-to-secure-an-api/
- https://auth0.com/learn/refresh-tokens
- https://web.archive.org/web/20220316130828/https://www.cidersecurity.io/top-10-cicd-security-risks/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1528/T1528.md
- https://github.com/danielmiessler/SecLists
- https://github.com/AonCyberLabs/PMapper
Unlock Pro Content
Get the full detection package for T1528 including response playbook, investigation guide, and atomic red team tests.