Attack Chokepoints 2 invariant stages
Each stage is an invariant condition the attacker must satisfy, regardless of tool, variant, or threat actor. Detection at any stage breaks the chain.
1 DRS Enrollment with Non-Native User Agent ▶
- Kit has already captured victim's session via AiTM relay (Tier 1 success)
- Kit holds a Microsoft Authentication Broker refresh token for the victim
- Victim tenant allows device registration (not restricted to Entra ID joined devices only)
- Kit has network access to enterpriseregistration.windows.net (DRS endpoint)
- Entra ID AuditLogs (AuditLogs table in Sentinel; filter ActivityDisplayName "Add registered users to device")
- Entra ID Sign-in Logs (cross-reference UPN for preceding AiTM sign-in within 5-15 min)
2 PRT Persistence Post-Revocation ▶
- Microsoft Graph Activity Logs (incomingTokenType field)
- Entra ID NonInteractiveUserSignInLogs
Variations 1 variant tracked
Tools and methods that exploit this chokepoint. The list grows. The chokepoint doesn't change.
Tycoon 2FA - Device PRT Enrollment Chain 2023-Q3 Active ▶
# Step 1: Resource-swap MAB refresh token for DRS access token
# User-Agent: axios/1.15.2
POST https://login.microsoftonline.com/common/oauth2/token
grant_type=refresh_token
refresh_token=<stolen_refresh_token>
resource=urn:ms-drs:enterpriseregistration.windows.net
client_id=29d9ed98-a469-4536-ade2-f981bc1d605e
# Step 2: Register synthetic device
# User-Agent: axios/1.15.2
POST https://enterpriseregistration.windows.net/EnrollmentServer/device
{"CertificateRequest":{"Type":"pkcs10","Data":"<base64_PKCS10_CSR>"},
"DeviceDisplayName":"<fabricated>","OSVersion":"<fabricated>"}
# Step 3-4: JWT bearer grant → obtain PRT
POST https://login.microsoftonline.com/common/oauth2/token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
assertion=<RS256_JWT_signed_with_device_key>
# Step 5: Ongoing - sign PRT assertions with HMAC-SHA256 session key
- Entra ID AuditLogs: operationName "Add registered users to device" resultType "0" userAgent "axios/1.15.2"
- Entra ID Device objects: fabricated DeviceDisplayName, OSVersion on registeredDevices/ownedDevices
- Graph Activity Logs: incomingTokenType "primaryRefreshToken" from cloud-VPS ASN post-revokeSignInSessions
Detection Strategy
Rules organized by the chokepoint stage they detect. Each stage has one or more rules at different maturity levels.
Analyst rule
▶
operationName == "Add registered users to device" AND resultType == "0" AND userAgent NOT contains_any [Dsreg, DeviceRegistrationClient, Dalvik] AND same UPN has preceding sign-in with Node.js UA within 15 minutes. Correlated alert: high confidence AiTM device-PRT persistence chain.
title: Entra ID AiTM Device PRT Enrollment — Non-Native UA Correlated with Preceding AiTM Sign-In
id: a7b8c9d0-e1f2-4a3b-4c5d-6e7f8a9b0c1d
status: experimental
description: >
Detects a synthetic Entra ID device registration (non-native UA) within 15 minutes
of a preceding AiTM kit relay sign-in (Node.js UA on OfficeHome/Auth Broker) for the
same UPN. This correlation confirms the Tycoon 2FA persistence chain: kit relay steals
session token → kit immediately enrolls synthetic device using DRS API with axios UA →
device-bound PRT acquired → persists through revokeSignInSessions. IR teams MUST delete
registered devices BEFORE revoking sessions; skipping device deletion leaves the PRT
active and allows immediate re-authentication.
NOTE: This rule requires correlation across two log sources (AuditLogs + SigninLogs) --
implement as KQL join or SIEM correlation rule.
KQL join (Sentinel):
let AiTMSignIn = SigninLogs
| where ResultType == "0"
and UserAgent has_any ("node","axios","undici","node-fetch")
and AppDisplayName has_any ("OfficeHome","Microsoft Authentication Broker")
| project AiTMTime = TimeGenerated, UserPrincipalName;
AuditLogs
| where OperationName == "Add registered users to device" and ResultType == "0"
| where not(UserAgent has_any ("Dsreg","DeviceRegistrationClient","Dalvik"))
| extend UPN = tostring(InitiatedBy.user.userPrincipalName)
| join kind=inner AiTMSignIn on $left.UPN == $right.UserPrincipalName
| where TimeGenerated between (AiTMTime .. AiTMTime + 15m)
references:
- https://www.elastic.co/security-labs/tycoon-2fa-aitm-detection-engineering
author: '@iimp0ster'
date: 2026-05-27
tags:
- attack.persistence
- attack.t1098.005
- detection.maturity.analyst
logsource:
product: azure
service: auditlogs
detection:
# This rule requires correlation across AuditLogs and SigninLogs — use the KQL join above.
# Sigma stub fires on device registration with non-native UA; full correlation requires SIEM.
selection_device_registration:
OperationName: 'Add registered users to device'
ResultType: '0'
filter_native_ua:
UserAgent|contains:
- 'Dsreg'
- 'DeviceRegistrationClient'
- 'Dalvik'
- 'Windows-AzureAD-Authentication-Provider'
# CORRELATION: same UPN in SigninLogs with Node.js UA within 900s preceding -- KQL required
condition: selection_device_registration and not filter_native_ua
falsepositives:
- Automated device enrollment workflows triggered by sign-in event (document and exclude)
- Split-session scenarios where Node.js tooling and device enrollment coincidentally overlap
level: high
Hunt rule
▶
operationName == "Add registered users to device" AND resultType == "0" AND userAgent NOT contains_any [Dsreg, DeviceRegistrationClient, Dalvik, Windows-AzureAD-Authentication-Provider]. Correlate with preceding AiTM sign-in from same UPN within 5-15 minutes (Node.js UA on OfficeHome/Auth Broker).
title: Entra ID Device Registration with Non-Native User Agent (AiTM PRT Persistence)
id: f6a7b8c9-d0e1-4f2a-3b4c-5d6e7f8a9b0c
status: experimental
description: >
Detects Entra ID device registration audit events where the initiating user agent
is not a native OS registration client. Tycoon 2FA's kit performs DRS
EnrollmentServer/device enrollment using axios/1.15.2, not the expected OS agents
(Dsreg, DeviceRegistrationClient, Dalvik, Windows-AzureAD-Authentication-Provider).
A registered device from a non-native UA obtains a PRT that survives
revokeSignInSessions, enabling persistent M365 access after IR response.
VERIFY field names (UserAgent vs. InitiatedBy.app.displayName or AdditionalDetails)
against lab AuditLogs data before production deployment.
references:
- https://www.elastic.co/security-labs/tycoon-2fa-aitm-detection-engineering
author: '@iimp0ster'
date: 2026-05-27
tags:
- attack.persistence
- attack.t1098.005
- detection.maturity.hunt
logsource:
product: azure
service: auditlogs
detection:
selection:
OperationName: 'Add registered users to device'
ResultType: '0'
filter_native_ua:
# Native OS registration clients — these are expected
UserAgent|contains:
- 'Dsreg'
- 'DeviceRegistrationClient'
- 'Dalvik'
- 'Windows-AzureAD-Authentication-Provider'
filter_known_automation:
# PENDING: Add documented automation service accounts or Intune pipeline identities
# InitiatedBy|contains:
# - 'svc-intune@tenant.onmicrosoft.com'
InitiatedBy: '' # placeholder — remove and populate before production
condition: selection and not filter_native_ua and not filter_known_automation
falsepositives:
- Third-party MDM solutions using custom HTTP clients for device enrollment
- Custom Intune enrollment wrappers with non-standard UA strings
- Vendor tooling not yet in the native UA filter
level: high
Research rule
▶
ActivityDisplayName == "Add device" OR operationName == "Add registered users to device" AND Result == "success". No UA filter - capture all to understand baseline enrollment volume and UA distribution.
title: Entra ID Device Registration Event (AiTM PRT Persistence Baseline)
id: e5f6a7b8-c9d0-4e1f-2a3b-4c5d6e7f8a9b
status: experimental
description: >
Baseline visibility rule: logs all successful Entra ID device registration
audit events (Add registered users to device). High FP rate from legitimate
Autopilot, Intune, and native device join operations — run for one week to
establish baseline and identify known-good user agents (Dsreg, Dalvik,
DeviceRegistrationClient) before promoting to hunt tier.
references:
- https://www.elastic.co/security-labs/tycoon-2fa-aitm-detection-engineering
author: '@iimp0ster'
date: 2026-05-27
tags:
- attack.persistence
- attack.t1098.005
- detection.maturity.research
logsource:
product: azure
service: auditlogs
detection:
selection:
OperationName: 'Add registered users to device'
ResultType: '0'
condition: selection
falsepositives:
- Legitimate Intune/Autopilot device enrollment (Dsreg UA)
- BYOD enrollment via Company Portal (DeviceRegistrationClient UA)
- Android device enrollment (Dalvik UA)
- Legitimate Azure AD join operations
level: informational