AiTM WebSocket Kit Relay

Server-side relay → Node.js HTTP client UA on Entra ID / Google sign-in event + cloud-VPS / residential two-tier ASN pattern within 20 minutes same UPN

Credential Access T1539 T1078.004 Detection difficulty: MEDIUM Prevalence: HIGH

Adversary-in-the-Middle (AiTM) kits operate a server-side WebSocket reverse proxy (typically Node.js + Socket.IO) that relays a victim's full authentication flow to Microsoft Entra ID or Google identity providers in real time, capturing post-MFA session tokens without touching the victim's endpoint. The kit relay tier makes server-to-server HTTP calls to Microsoft/Google using a Node.js HTTP client, which leaves a distinctive user agent (node, axios, undici, node-fetch) on sign-in events. Operators then access the compromised account from residential-proxy infrastructure, creating a two-tier ASN pattern that is structurally unavoidable: cloud-VPS for kit relay performance, residential proxy for operator evasion. Both tiers authenticate as the same UPN within ~20 minutes - a high-confidence correlation no single-ASN rule catches. The Google variant additionally compresses the full authentication sequence (login_success → MFA relay → OAuth token → device registration) into ~1 second - mechanically impossible for human interaction.

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 Kit Relay Sign-In (Node.js UA) ▶
  • Victim must visit a phishing page that loads the kit's JavaScript (delivered via email link, QR code, PDF/SVG/HTML attachment lure)
  • Kit server must be running and reachable from victim's browser
  • Target must be a cloud identity tenant (Microsoft 365 / Entra ID or Google Workspace) where the kit can proxy the login flow to the real IdP
  • Victim must complete MFA challenge (kit relays all MFA methods except FIDO2/passkeys, which cryptographically bind to the legitimate origin domain)
Input Victim has completed MFA on the phishing page; kit has relayed credentials server-side to Microsoft/Google
Chokepoint The attacker MUST make server-to-server HTTP calls to Microsoft/Google login endpoints using a non-browser HTTP client (Node.js) - these calls appear in Entra ID sign-in logs with the kit's user agent.
Observable Entra ID SigninLogs: resultType == "0" (success) AND userAgent contains node / axios / undici / node-fetch AND appDisplayName contains OfficeHome / Microsoft Authentication Broker / Microsoft Graph / Microsoft Exchange Online. Google Workspace Login Audit: login_success → login_verification (is_second_factor: true) → token:authorize (Chrome OAuth client 77185425430) → DEVICE_REGISTER_UNREGISTER_EVENT - all within ~1 second.
Why unavoidable
The AiTM relay is server-side: the kit's Node.js process makes the actual HTTP calls to Microsoft/Google on behalf of the victim. Using a browser UA on these server-to-server calls would require rewriting the kit's HTTP client as a headless browser, which breaks the WebSocket relay architecture and would still generate anomalous behavioral signals (headless browser on server infra). The user agent cannot be spoofed to match a legitimate end-user browser session without making the relay technically infeasible.
  • Entra ID Sign-in Logs (SigninLogs table in Microsoft Sentinel)
  • Google Workspace Login Audit (login, token activity events)
View rule →
↓ Kit relay (Tier 1) has completed session token capture; o...
2 Two-Tier ASN Transition ▶
Input Kit relay (Tier 1) has completed session token capture; operator console (Tier 2) begins accessing the victim account 10-20 minutes later
Chokepoint The attacker MUST use two structurally distinct ASN categories - cloud-VPS for the high-throughput kit relay and residential/ISP proxy for the operator console accessing M365 web apps - creating a detectable dual-ASN authentication pattern for the same UPN within a short window.
Observable Entra ID SigninLogs: Two successful sign-ins by the same UPN within 20 minutes where one source IP belongs to a cloud-hosting ASN (Alibaba Cloud, M247, DigitalOcean, Linode, OVH, Hetzner, Clouvider) and the other to a residential or small-ISP ASN. The cloud-VPS sign-in has Node.js UA; the residential sign-in has a browser UA accessing My Profile / My Signins / OfficeHome / Outlook Web. Shared c_sid in Graph Activity Logs across multiple /24 IPs confirms Tier 2 operator console coordination.
Why unavoidable
The two-tier architecture is structurally required: the kit relay needs high- throughput cloud VPS infrastructure to proxy real-time WebSocket sessions at scale, while the operator console must use residential-shaped ASNs to evade geo-velocity and IP risk scoring. The attacker cannot use the same cloud-VPS ASN for both tiers without triggering geo-velocity alerts; cannot use residential proxy for the kit relay without unacceptable throughput degradation.
  • Entra ID Sign-in Logs with ASN enrichment (GeoIP/ASN database required)
  • Microsoft Graph Activity Logs (c_sid correlation across /24 IPs)
⚠ Bypass risk: Single-ASN rules miss one tier entirely. Attackers may attempt to flatten the two-tier model by routing both relay and console through residential proxies, trading throughput for evasion. Monitor for Node.js UA on residential ASNs as a bypass adaptation indicator.
View rule →

Variations 2 variants tracked

Tools and methods that exploit this chokepoint. The list grows. The chokepoint doesn't change.

Tycoon 2FA (Storm-1747) - WebSocket Variant 2023-Q3 Active ▶
Most prolific AiTM PhaaS kit as of 2025; ~62% of AiTM phishing blocked by Microsoft. Uses Socket.IO 4.6.0 with recieveid (typo) event name fingerprint. Tier 1: Alibaba Cloud / cheap-VPS ASNs, axios/1.15.2 / undici user agents. Tier 2: Residential ISP proxy, browser UA (Firefox on Windows), accesses My Profile / My Signins / Microsoft Approval Management / Outlook Web / OfficeHome ~10-20 minutes post-relay.
Storm-1747 PhaaS. Kit relay uses Node.js HTTP clients (node, axios/1.15.2, undici, node-fetch). Operator console appears 10-20 minutes later on residential proxy. Entra sign-in log shows Node.js UA on OfficeHome/Auth Broker as the primary Tier 1 signal.
# Kit relay tier (cloud VPS) - server-to-server calls:
# User-Agent: axios/1.15.2
POST https://login.microsoftonline.com/common/oauth2/token [Kit relay]
# Socket.IO relay events:
# send_to_browser / response_from_browser / recieveid (typo fingerprint)
#
# Google variant - 4-event sequence within ~1s:
# login_success → login_verification(is_second_factor:true) →
# token:authorize(client:77185425430) → DEVICE_REGISTER_UNREGISTER_EVENT
  • Entra ID SigninLogs: userAgent contains axios/1.15.2 on appDisplayName OfficeHome/Microsoft Authentication Broker
  • Entra ID SigninLogs: Residential ASN sign-in 10-20 min after cloud-VPS sign-in, same UPN
  • Graph Activity Logs: shared c_sid across multiple /24 IPs (Tier 2 operator console)
  • Google Workspace Login Audit: 4-event sequence compressed to <1.2 seconds
Same chokepoint: Victim visits phishing page → Kit relays auth via Node.js (axios UA on Entra sign-in) → Session tokens captured → Operator console (residential ASN) accesses M365 web apps
Source: www.elastic.co →
EvilProxy 2022-Q3 Active ▶
Commercial AiTM reverse proxy service targeting Microsoft 365 and Google. Uses similar reverse-proxy architecture but typically routes through dedicated relay infrastructure. Generates same class of server-to-server sign-in events with non-browser user agents.
Commercial AiTM proxy targeting C-suite. Same detection chokepoint applies - server-side relay must make HTTP calls to Microsoft/Google with non-browser UA.
# EvilProxy architecture similar to Tycoon 2FA
# Server-side relay generates non-browser UA on IdP sign-in events
  • Entra ID SigninLogs: non-browser user agent on O365 sign-in events
  • Two-tier ASN pattern when operator console is distinct from relay infra
Same chokepoint: Phishing page → EvilProxy relay (non-browser UA on Entra sign-in) → Session theft → Operator access
Source: www.proofpoint.com →

Detection Strategy

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

1 Kit Relay Sign-In (Node.js UA)
Hunt rule
▶
Goal
Node.js user agent on Entra sign-in to high-value M365 apps (OfficeHome, Auth Broker, Graph, Exchange Online). Filters out low-value apps.
Log Sources
  • Entra ID Sign-in Logs
FP Rate
Low-Medium
Use Case
Active hunting for kit relay tier. High-value app filter reduces FP rate from legitimate Graph API automation while preserving coverage of the most common Tycoon 2FA relay targets.
resultType == "0" AND userAgent contains_any [node, axios, undici, node-fetch] AND appDisplayName contains_any [OfficeHome, Microsoft Authentication Broker, Microsoft Graph, Microsoft Exchange Online]. Exclude known-good service accounts with documented Node.js automation.
Sigma Rule - Hunt Level
title: Entra ID AiTM Kit Relay via Node.js User Agent on High-Value M365 App
id: a2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: >
  Detects Entra ID sign-ins with Node.js HTTP client user agents (node, axios, undici,
  node-fetch) on high-value Microsoft 365 applications (OfficeHome, Microsoft Authentication
  Broker, Microsoft Graph, Exchange Online). Characteristic of Tycoon 2FA and other AiTM
  kit relay tiers making server-to-server HTTP calls to relay victim sessions.
  Normal M365 sign-ins use browser user agents — Node.js on these apps indicates
  a server-side relay component, not an end-user browser session.
references:
  - https://www.elastic.co/security-labs/tycoon-2fa-aitm-detection-engineering
author: '@iimp0ster'
date: 2026-05-27
tags:
  - attack.credential-access
  - attack.t1539
  - attack.t1078.004
  - detection.maturity.hunt
logsource:
  product: azure
  service: signinlogs
detection:
  selection_success:
    ResultType: '0'
  selection_ua:
    UserAgent|contains:
      - 'node'
      - 'axios'
      - 'undici'
      - 'node-fetch'
  selection_app:
    AppDisplayName|contains:
      - 'OfficeHome'
      - 'Microsoft Authentication Broker'
      - 'Microsoft Graph'
      - 'Microsoft Exchange Online'
  filter_legit_automation:
    # PENDING: Add known-good service account UPNs with documented Node.js automation
    # UserPrincipalName|contains:
    #   - 'svc-graphapi@tenant.onmicrosoft.com'
    UserPrincipalName: ''  # placeholder — remove and populate before production
  condition: selection_success and selection_ua and selection_app and not filter_legit_automation
falsepositives:
  - Legitimate server-side automation using Node.js Graph SDK targeting these apps
  - DevOps pipelines with documented Graph API integration to Exchange/OfficeHome
  - Exclude known-good service accounts in filter_legit_automation
level: high
2 Two-Tier ASN Transition
Hunt rule
▶
Goal
Node.js user agent on Entra sign-in to high-value M365 apps (OfficeHome, Auth Broker, Graph, Exchange Online). Filters out low-value apps.
Log Sources
  • Entra ID Sign-in Logs
FP Rate
Low-Medium
Use Case
Active hunting for kit relay tier. High-value app filter reduces FP rate from legitimate Graph API automation while preserving coverage of the most common Tycoon 2FA relay targets.
resultType == "0" AND userAgent contains_any [node, axios, undici, node-fetch] AND appDisplayName contains_any [OfficeHome, Microsoft Authentication Broker, Microsoft Graph, Microsoft Exchange Online]. Exclude known-good service accounts with documented Node.js automation.
Sigma Rule - Hunt Level
title: Entra ID AiTM Kit Relay via Node.js User Agent on High-Value M365 App
id: a2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: >
  Detects Entra ID sign-ins with Node.js HTTP client user agents (node, axios, undici,
  node-fetch) on high-value Microsoft 365 applications (OfficeHome, Microsoft Authentication
  Broker, Microsoft Graph, Exchange Online). Characteristic of Tycoon 2FA and other AiTM
  kit relay tiers making server-to-server HTTP calls to relay victim sessions.
  Normal M365 sign-ins use browser user agents — Node.js on these apps indicates
  a server-side relay component, not an end-user browser session.
references:
  - https://www.elastic.co/security-labs/tycoon-2fa-aitm-detection-engineering
author: '@iimp0ster'
date: 2026-05-27
tags:
  - attack.credential-access
  - attack.t1539
  - attack.t1078.004
  - detection.maturity.hunt
logsource:
  product: azure
  service: signinlogs
detection:
  selection_success:
    ResultType: '0'
  selection_ua:
    UserAgent|contains:
      - 'node'
      - 'axios'
      - 'undici'
      - 'node-fetch'
  selection_app:
    AppDisplayName|contains:
      - 'OfficeHome'
      - 'Microsoft Authentication Broker'
      - 'Microsoft Graph'
      - 'Microsoft Exchange Online'
  filter_legit_automation:
    # PENDING: Add known-good service account UPNs with documented Node.js automation
    # UserPrincipalName|contains:
    #   - 'svc-graphapi@tenant.onmicrosoft.com'
    UserPrincipalName: ''  # placeholder — remove and populate before production
  condition: selection_success and selection_ua and selection_app and not filter_legit_automation
falsepositives:
  - Legitimate server-side automation using Node.js Graph SDK targeting these apps
  - DevOps pipelines with documented Graph API integration to Exchange/OfficeHome
  - Exclude known-good service accounts in filter_legit_automation
level: high
+ Research detection tier
Research rule
▶
Goal
Log all Entra ID sign-ins where the user agent contains Node.js HTTP client strings. Establishes baseline of legitimate Node.js SDK usage vs. kit relay.
Log Sources
  • Entra ID Sign-in Logs (SigninLogs / AADSignInEventsBeta in MDE)
resultType == "0" AND userAgent contains_any [node, axios, undici, node-fetch, node-fetch/1.0]. No app filter - capture all apps to build baseline of legitimate Node.js automation. Run for one week to identify known-good DevOps pipelines and IT automation.
Sigma Rule - Research Level
title: Entra ID Sign-In with Node.js User Agent (AiTM Kit Relay Baseline)
id: f1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c
status: experimental
description: >
  Baseline visibility rule: logs all successful Entra ID sign-ins where the user agent
  contains Node.js HTTP client strings (node, axios, undici, node-fetch). High FP rate
  from legitimate Graph API automation — run for one week to build allowlist 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.credential-access
  - attack.t1539
  - detection.maturity.research
logsource:
  product: azure
  service: signinlogs
detection:
  selection_success:
    ResultType: '0'
  selection_ua:
    UserAgent|contains:
      - 'node'
      - 'axios'
      - 'undici'
      - 'node-fetch'
  condition: selection_success and selection_ua
falsepositives:
  - Legitimate Node.js SDK automation against Microsoft Graph API
  - DevOps pipelines using Azure CLI or Graph SDK
  - IT automation scripts using Node.js HTTP clients
  - Service accounts with documented Node.js tooling
level: informational
+ Analyst detection tier
Analyst rule
Low FP
▶
Goal
Two-tier ASN correlation: cloud-VPS ASN and residential/ISP ASN both authenticating as the same UPN within 20 minutes. High-confidence AiTM signal that survives user agent rotation.
Log Sources
  • Entra ID Sign-in Logs with ASN enrichment
Requires ASN enrichment lookup on source IP. Alert when same UPN has two successful sign-ins within 20 minutes where ASN1 is a cloud-hosting provider (Alibaba Cloud, M247, DigitalOcean, Linode, OVH, Hetzner, Clouvider, Host Telecom) AND ASN2 is a residential ISP or small proxy ASN. Exclude known corporate VPN egress ASNs.
Sigma Rule - Analyst Level
title: Entra ID Two-Tier ASN AiTM Pattern — Same UPN Cloud-VPS and Residential within 20 Minutes
id: b3c4d5e6-f7a8-4b9c-0d1e-2f3a4b5c6d7e
status: experimental
description: >
  Detects two successful Entra ID sign-ins by the same UPN within 20 minutes where one
  source IP is from a cloud-hosting/VPS ASN and the other is from a residential or small-ISP
  ASN. This two-tier ASN pattern is structurally required by AiTM kits: cloud-VPS for the
  high-throughput kit relay, residential proxy for the operator console. Single-ASN rules
  miss one tier. This rule targets the architectural requirement and survives user agent rotation.
  REQUIRES ASN enrichment lookup on source IP against a cloud-provider ASN list.
  NOTE: This rule requires correlation across two sign-in events and ASN enrichment --
  implement in SIEM with lookup table or KQL join rather than standard Sigma evaluation.
references:
  - https://www.elastic.co/security-labs/tycoon-2fa-aitm-detection-engineering
author: '@iimp0ster'
date: 2026-05-27
tags:
  - attack.credential-access
  - attack.t1539
  - attack.t1078.004
  - detection.maturity.analyst
logsource:
  product: azure
  service: signinlogs
detection:
  # This rule requires correlation and ASN enrichment — the detection block below
  # is a conceptual stub. Implement via KQL join or SIEM correlation rule.
  selection_cloud_vps:
    ResultType: '0'
    # EnrichedASN field (requires lookup table enrichment):
    # EnrichedASNCategory: 'cloud-hosting'
    # Cloud-hosting ASN examples: Alibaba Cloud (AS37963), M247 (AS9009),
    # DigitalOcean (AS14061), Linode/Akamai (AS63949), OVH (AS16276),
    # Hetzner (AS24940), Clouvider (AS62240), Host Telecom
    UserAgent|contains:
      - 'node'
      - 'axios'
      - 'undici'
      - 'node-fetch'
  selection_residential:
    ResultType: '0'
    # EnrichedASNCategory: 'residential-isp'
    UserAgent|contains:
      - 'Mozilla'
    AppDisplayName|contains:
      - 'OfficeHome'
      - 'My Signins'
      - 'Microsoft Approval Management'
      - 'Outlook Web'
  # CORRELATION: same UserPrincipalName across both sign-ins within 1200 seconds (20 min)
  # STUB -- verify log source and field names against lab data; implement as SIEM correlation
  condition: selection_cloud_vps
falsepositives:
  - Corporate VPN egress shared across multiple ASN categories (exclude corporate VPN IPs)
  - Legitimate split-routing scenarios (mobile + desktop same UPN)
  - Known corporate proxies in non-cloud ASNs
level: high

OSINT Pivots