T1586.002 Microsoft Sentinel · KQL

Detect Email Accounts in Microsoft Sentinel

Adversaries may compromise existing email accounts to support operations. Unlike creating new accounts, compromising legitimate accounts leverages established trust relationships, bypasses reputation-based email filters, and enables thread hijacking. Compromise methods include credential phishing, password reuse from breach dumps, brute force, and insider access (buying credentials from employees). Threat actors including APT28, APT29, Kimsuky, OilRig, Star Blizzard, and LAPSUS$ have all used compromised email accounts to conduct spearphishing, harvest additional credentials, and acquire infrastructure. Because the compromise itself occurs externally, detection must focus on observable post-compromise behaviors within the organization: risky sign-in patterns, impossible travel, inbox rule manipulation, bulk sending anomalies, and thread hijacking indicators.

MITRE ATT&CK

Tactic
Resource Development
Technique
T1586 Compromise Accounts
Sub-technique
T1586.002 Email Accounts
Canonical reference
https://attack.mitre.org/techniques/T1586/002/

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
// T1586.002 — Compromised Email Account Detection
// Detects post-compromise behaviors: impossible travel, risky sign-ins,
// inbox rule creation/forwarding setup, and bulk outbound email anomalies.

let LookbackWindow = 24h;
let ImpossibleTravelThreshold = 2; // distinct countries within 1 hour
let BulkSendThreshold = 50; // emails sent in 1 hour

// Branch 1: Risky or impossible travel sign-ins to email services
let RiskySignIns =
SigninLogs
| where TimeGenerated > ago(LookbackWindow)
| where ResultType == "0" // Successful sign-in only — compromise achieved
| where AppDisplayName has_any ("Exchange", "Outlook", "Office 365", "Microsoft 365", "Exchange Online", "OWA")
| where RiskLevelDuringSignIn in ("high", "medium") or RiskState == "atRisk"
    or IsRisky == true
| extend Country = tostring(Location.countryOrRegion)
| extend City = tostring(Location.city)
| project TimeGenerated, UserPrincipalName, IPAddress, Country, City,
          AppDisplayName, DeviceDetail, RiskLevelDuringSignIn, RiskState,
          RiskDetail, AutonomousSystemNumber, AuthenticationRequirement,
          ConditionalAccessStatus
| extend DetectionBranch = "RiskySignIn";

// Branch 2: Impossible travel — same account from multiple countries within 1 hour
let ImpossibleTravel =
SigninLogs
| where TimeGenerated > ago(LookbackWindow)
| where ResultType == "0"
| where AppDisplayName has_any ("Exchange", "Outlook", "Office 365", "Microsoft 365", "Exchange Online", "OWA")
| extend Country = tostring(Location.countryOrRegion)
| summarize
    Countries = make_set(Country),
    IPAddresses = make_set(IPAddress),
    SignInCount = count(),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
  by UserPrincipalName, bin(TimeGenerated, 1h)
| where array_length(Countries) >= ImpossibleTravelThreshold
| extend DetectionBranch = "ImpossibleTravel"
| project FirstSeen, UserPrincipalName, Countries, IPAddresses, SignInCount, DetectionBranch;

// Branch 3: Inbox rule creation or email forwarding configured post-sign-in
let InboxRuleCreation =
OfficeActivity
| where TimeGenerated > ago(LookbackWindow)
| where Operation in (
    "New-InboxRule", "Set-InboxRule", "UpdateInboxRules",
    "Set-Mailbox", "Set-MailboxAutoReplyConfiguration"
  )
| where Parameters has_any (
    "ForwardTo", "ForwardAsAttachmentTo", "RedirectTo",
    "DeleteMessage", "MarkAsRead", "MoveToFolder"
  )
| extend RuleParameters = tostring(Parameters)
| project TimeGenerated, UserId, ClientIP, Operation, RuleParameters,
          OfficeWorkload, OrganizationName
| extend DetectionBranch = "InboxRuleManipulation";

// Branch 4: High-volume email sending anomaly (bulk phishing from compromised account)
let BulkSending =
OfficeActivity
| where TimeGenerated > ago(LookbackWindow)
| where Operation == "Send"
| where OfficeWorkload == "Exchange"
| summarize
    EmailsSent = count(),
    UniqueRecipients = dcount(tostring(parse_json(tostring(Parameters))[0].Value)),
    FirstSend = min(TimeGenerated),
    LastSend = max(TimeGenerated)
  by UserId, ClientIP, bin(TimeGenerated, 1h)
| where EmailsSent >= BulkSendThreshold
| extend DetectionBranch = "BulkEmailSending"
| project FirstSend, UserId, ClientIP, EmailsSent, UniqueRecipients, DetectionBranch;

// Combine all branches
RiskySignIns
| union (ImpossibleTravel | project TimeGenerated = FirstSeen, UserPrincipalName, DetectionBranch, IPAddress = tostring(IPAddresses))
| union (InboxRuleCreation | project TimeGenerated, UserPrincipalName = UserId, DetectionBranch, IPAddress = ClientIP)
| union (BulkSending | project TimeGenerated = FirstSend, UserPrincipalName = UserId, DetectionBranch, IPAddress = ClientIP)
| sort by TimeGenerated desc
high severity medium confidence

Detects post-compromise behaviors indicative of a hijacked email account using Azure AD SigninLogs and OfficeActivity tables. Four detection branches: (1) high-risk sign-ins to Exchange/Outlook services flagged by Azure AD Identity Protection, (2) impossible travel — same account authenticated from multiple countries within a 1-hour window, (3) inbox rule creation or email forwarding configured after sign-in, which adversaries use to silently collect email or redirect messages, and (4) bulk outbound email anomalies suggesting the account is being used for phishing campaigns. All branches produce actionable events for SOC triage.

Data Sources

Application Log: Application Log ContentNetwork Traffic: Network Traffic ContentMicrosoft 365 Unified Audit LogAzure AD Identity Protection

Required Tables

SigninLogsOfficeActivity

False Positives & Tuning

  • Legitimate travel: employees using email from multiple countries in rapid succession (e.g. layovers, VPN with auto-selected exit nodes, or roaming with split-tunnel VPN)
  • IT administrators creating inbox rules or forwarding configurations on behalf of users during mailbox migrations, offboarding, or automated workflow setup
  • Marketing automation or bulk email campaigns sent through compromised-looking patterns when authorized tools (Mailchimp, HubSpot) relay via Exchange
  • Azure AD Identity Protection flagging sign-ins from corporate IP ranges not yet registered as named locations, generating false risk scores
  • Service accounts or shared mailboxes that legitimately sign in from multiple locations or send high volumes of transactional email
Download portable Sigma rule (.yml)

Other platforms for T1586.002


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.

  1. Test 1Simulate Compromised Account Inbox Rule Creation

    Expected signal: Office 365 Unified Audit Log: Operation='New-InboxRule', UserId='[email protected]', Parameters containing 'ForwardTo' and '[email protected]'. Event appears in OfficeActivity table in Sentinel within ~15 minutes of creation. ClientIP will reflect the machine running the PowerShell session.

  2. Test 2Credential Spray Simulation Against Exchange Online

    Expected signal: Azure AD SigninLogs: multiple entries with ResultType='50126' (invalid credentials) or '50055' for target UserPrincipalName from the executing machine's IP address. AppDisplayName will show 'Exchange Web Services' or 'Outlook'. AuthenticationProtocol will show 'Legacy' indicating Basic Auth. Failed attempts trigger Azure AD Identity Protection spray detection after threshold.

  3. Test 3Simulate Bulk Email Send from Compromised Account

    Expected signal: OfficeActivity table: multiple Operation='Send' entries from [email protected] within a 1-hour window, UserId matching the test account, ClientIP matching the executing machine. Email count will exceed the BulkSendThreshold (50) for the hourly bucket, triggering the bulk sending branch.

  4. Test 4Verify Impossible Travel Detection Using VPN Geo-Shift

    Expected signal: Azure AD SigninLogs: two entries for the test account within ~20 minutes showing different Location.countryOrRegion values (e.g. 'United States' and 'Germany'). ResultType='0' for both (successful). Azure AD Identity Protection may independently raise a 'impossibleTravel' risk detection within minutes.

Unlock Pro Content

Get the full detection package for T1586.002 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections