AiTM Kit Device PRT Enrollment

DRS EnrollmentServer/device call with non-native UA (axios/1.15.2 not Dsreg) → Entra ID audit event → device-bound PRT surviving revokeSignInSessions

Persistence T1098.005 Detection difficulty: LOW Prevalence: MEDIUM

After capturing a victim's session via AiTM proxy, the Tycoon 2FA kit registers a synthetic device with Microsoft Device Registration Service (DRS) to obtain a Primary Refresh Token (PRT) bound to a kit-controlled device object. This PRT survives the standard IR playbook of revokeSignInSessions because the device is a separate Entra ID principal - its PRT remains valid indefinitely unless the device object is explicitly deleted first. The enrollment call always uses the kit's Node.js HTTP client (axios/1.15.2), not the native Entra ID join clients (Dsreg, DeviceRegistrationClient, Dalvik) - a binary distinction exploitable as a high-fidelity detection. Critical IR finding: the correct containment sequence is atomically disable account → enumerate and DELETE all registered devices → THEN revoke sign-in sessions → reset password. Reversing steps 2 and 3 leaves the device-PRT valid and allows the kit to continue brokering fresh access tokens via HMAC-SHA256 signed PRT assertions.

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)
Input Kit has captured MAB refresh token; proceeds to register synthetic device for PRT persistence
Chokepoint The attacker MUST call the DRS EnrollmentServer/device endpoint to register a device - this is the only path to a device-bound PRT in Entra ID. The enrollment always generates an audit event in Entra ID AuditLogs. The kit's HTTP client (axios/1.15.2) is the user agent on this call, not the native clients (Dsreg / DeviceRegistrationClient / Dalvik) used by legitimate join workflows.
Observable Entra ID AuditLogs: operationName == "Add registered users to device" AND resultType == "0" (success) AND userAgent NOT IN [Dsreg, DeviceRegistrationClient, Dalvik, Windows-AzureAD-Authentication-Provider]. The non-native UA is the binary invariant - legitimate device enrollment from managed endpoints never uses axios or node.
Why unavoidable
DRS EnrollmentServer/device is the only API path to obtain a device-bound PRT in Entra ID. There is no alternative enrollment mechanism. The audit event is generated server-side by Microsoft's DRS - the attacker cannot suppress it. The kit cannot use native Dsreg/DeviceRegistrationClient because those are Windows OS components that would require code execution on a managed endpoint, defeating the purpose of the cloud-side AiTM kit.
  • 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)
View rule →
↓ IR team has executed revokeSignInSessions (but NOT delete...
2 PRT Persistence Post-Revocation ▶
Input IR team has executed revokeSignInSessions (but NOT deleted device objects first)
Chokepoint The attacker MUST use the PRT + session key to sign per-request HMAC-SHA256 assertions for ongoing oauth2/token calls - these generate non-interactive sign-in records with incomingTokenType: primaryRefreshToken even after revokeSignInSessions has been executed.
Observable Microsoft Graph Activity Logs or Entra ID NonInteractiveUserSignInLogs: incomingTokenType == "primaryRefreshToken" from same UPN AFTER a revokeSignInSessions event. This confirms device-PRT is still active and device objects were not deleted before session revocation.
Why unavoidable
PRT token grants always log incomingTokenType in Microsoft's audit infrastructure. The attacker cannot obtain fresh access tokens without making oauth2/token calls that generate log entries. The signal is generated server-side by Microsoft.
  • Microsoft Graph Activity Logs (incomingTokenType field)
  • Entra ID NonInteractiveUserSignInLogs
⚠ Bypass risk: If IR deletes device objects before revoking sessions (correct order), the PRT is invalidated and this stage never fires. This stage is a post-IR-failure indicator, not a preventive detection.
View rule →

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 ▶
Full API call chain documented by Elastic Security Labs. Five steps: (1) Resource-swap MAB refresh token for DRS access token at oauth2/token (resource=urn:ms-drs:enterpriseregistration.windows.net). (2) POST EnrollmentServer/device with PKCS#10 CSR + synthetic device metadata. (3) Build RS256 JWT signed with kit-generated device private key. (4) POST jwt-bearer grant to obtain PRT + encrypted session key. (5) Sign per-request HMAC-SHA256 PRT assertions for ongoing access. User agent on enrollment call: axios/1.15.2.
Audit event fires on Step 2 (DRS enrollment). Kit user agent (axios/1.15.2) is the binary distinguishing signal vs. legitimate Dsreg/DeviceRegistrationClient. PRT obtained in Step 4 survives revokeSignInSessions - device must be deleted first.
# 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
Same chokepoint: Kit captures session → axios enrolls DRS device (audit event) → PRT obtained → survives revokeSignInSessions → ongoing non-interactive sign-ins
Source: www.elastic.co →

Detection Strategy

Rules organized by the chokepoint stage they detect. Each stage has one or more rules at different maturity levels.

1 DRS Enrollment with Non-Native User Agent
Analyst rule
▶
Goal
Device registration with non-native UA correlated with preceding AiTM sign-in signal from same UPN within 15 minutes.
Log Sources
  • Entra ID AuditLogs
  • Entra ID Sign-in Logs (for AiTM correlation)
FP Rate
Very Low
Use Case
SOC alerting. Immediate IR escalation. Trigger automated response: disable account → delete registered devices → revoke sessions → reset password.
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.
⚠ Correlation required: This rule covers one stage only. See the description for SIEM-side join guidance.
Sigma Rule - Analyst Level
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
2 PRT Persistence Post-Revocation
Hunt rule
▶
Goal
Device registration with user agent NOT in the native Entra ID join client set. High-fidelity due to binary distinction between kit and native clients.
Log Sources
  • Entra ID AuditLogs
FP Rate
Low (custom MDM tools with non-standard UAs; document and exclude)
Use Case
Active hunting for device-PRT persistence. High-fidelity due to binary UA distinction. False positives limited to bespoke MDM automation.
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).
Sigma Rule - Hunt Level
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 detection tier
Research rule
▶
Goal
Log all successful device registration audit events regardless of user agent. Baseline for understanding legitimate enrollment patterns.
Log Sources
  • Entra ID AuditLogs
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.
Sigma Rule - Research Level
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