T1585

Establish Accounts

Resource Development Last updated:

This detection identifies observable indicators of adversary account establishment activity within the target environment — specifically inbound communications from newly created or privacy-focused email accounts targeting multiple employees, suspicious authentication attempts from externally established personas, and endpoint connections to account creation infrastructure. Since T1585 is a PRE-ATT&CK technique occurring outside the victim network, detections focus on the downstream effects: spearphishing precursor activity from zero-history email accounts, bulk contact campaigns from free/disposable email providers, and network telemetry showing corporate endpoints researching persona-associated platforms. Coverage spans all three sub-techniques: social media (T1585.001), email (T1585.002), and cloud account (T1585.003) establishment.

What is T1585 Establish Accounts?

Establish Accounts (T1585) maps to the Resource Development tactic — the adversary is trying to establish resources they can use to support operations in MITRE ATT&CK.

This page provides production-ready detection logic for Establish Accounts, covering the data sources and telemetry it touches: Microsoft Defender for Office 365. The queries below are rated medium severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Resource Development
Technique
T1585 Establish Accounts
Canonical reference
https://attack.mitre.org/techniques/T1585/
Microsoft Sentinel / Defender
kusto
let PrivacyEmailDomains = dynamic([
    "protonmail.com", "proton.me", "tutanota.com", "tutamail.com",
    "cock.li", "disroot.org", "riseup.net", "mailfence.com",
    "guerrillamail.com", "temp-mail.org", "mailinator.com",
    "10minutemail.com", "throwam.com", "yopmail.com"
]);
let SuspiciousFreeProviders = dynamic([
    "gmail.com", "yahoo.com", "hotmail.com", "outlook.com",
    "live.com", "icloud.com", "aol.com"
]);
let LookbackDays = 14d;
EmailEvents
| where TimeGenerated > ago(LookbackDays)
| where DeliveryAction in ("Delivered", "Junked", "Blocked")
| where EmailDirection == "Inbound"
| extend SenderDomain = tolower(tostring(split(SenderFromAddress, "@")[1]))
| where SenderDomain in~ (PrivacyEmailDomains) or SenderDomain in~ (SuspiciousFreeProviders)
| summarize
    EmailCount = count(),
    TargetedUsers = dcount(RecipientEmailAddress),
    TargetedRecipients = make_set(RecipientEmailAddress, 10),
    AttachmentEmails = countif(AttachmentCount > 0),
    LinkEmails = countif(UrlCount > 0),
    DeliveredCount = countif(DeliveryAction == "Delivered"),
    JunkedCount = countif(DeliveryAction == "Junked"),
    SampleSubjects = make_set(Subject, 5),
    FirstContact = min(TimeGenerated),
    LastContact = max(TimeGenerated)
    by SenderFromAddress, SenderDomain
| extend
    CampaignDurationHours = datetime_diff("hour", LastContact, FirstContact),
    IsPrivacyProvider = SenderDomain in~ (PrivacyEmailDomains),
    IsFreeProvider = SenderDomain in~ (SuspiciousFreeProviders)
| extend RiskScore =
    // Multi-target contact is a strong signal
    case(TargetedUsers >= 10, 40, TargetedUsers >= 5, 25, TargetedUsers >= 2, 10, 0)
    // Privacy/anonymous providers weighted higher
    + case(IsPrivacyProvider, 25, IsFreeProvider and TargetedUsers >= 3, 15, 0)
    // Attachment-bearing emails increase risk
    + case(AttachmentEmails >= 3, 20, AttachmentEmails >= 1, 10, 0)
    // Link-only campaigns (credential harvest setup)
    + case(LinkEmails >= 5 and AttachmentEmails == 0, 15, LinkEmails >= 2, 8, 0)
    // Burst pattern within short window
    + case(EmailCount >= 5 and CampaignDurationHours <= 2, 15, 0)
| where RiskScore >= 25
| project
    TimeGenerated = FirstContact,
    SenderFromAddress,
    SenderDomain,
    IsPrivacyProvider,
    EmailCount,
    TargetedUsers,
    TargetedRecipients,
    AttachmentEmails,
    LinkEmails,
    DeliveredCount,
    JunkedCount,
    CampaignDurationHours,
    SampleSubjects,
    RiskScore,
    LastContact
| order by RiskScore desc

Detects inbound email campaigns from privacy-focused or free email providers targeting multiple employees, a behavioral signature of adversary persona-based spearphishing precursor activity. Scores risk based on provider type, number of targeted users, presence of attachments or links, and burst timing patterns consistent with automated persona-driven contact campaigns.

medium severity medium confidence

Data Sources

Microsoft Defender for Office 365

Required Tables

EmailEvents

False Positives

  • Legitimate mass newsletters or marketing emails from Gmail/Yahoo senders — filter by adding known sender domains to allowlist
  • Corporate recruitment contacts from candidates using personal email accounts targeting HR or hiring managers
  • External security researchers or vendors using ProtonMail for legitimate privacy reasons contacting security teams
  • Conference or event organizers using free email providers sending bulk invitations to multiple employees

Sigma rule & cross-platform mapping

The detection logic for Establish Accounts (T1585) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  product: azure

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 3 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 Persona-Based Inbound Email Campaign from Privacy Provider

    Expected signal: EmailEvents table in Microsoft Defender for Office 365 should show matching records; Message Trace output confirms telemetry is flowing for privacy-provider senders

  2. Test 2Test Network Detection for Social Media Account Registration Activity

    Expected signal: Sysmon Event ID 22 (DNS Query) for registration domains; DeviceNetworkEvents ConnectionSuccess/ConnectionAttempted events for HTTPS connections to signup paths

  3. Test 3Simulate Cloud Account Creation for Persona Infrastructure (Azure CLI)

    Expected signal: AuditLogs in Azure AD / Microsoft Sentinel: Operation=Add application or Invite external user, Category=ApplicationManagement or UserManagement. CloudAppEvents table should show account creation activity.


Response Playbook

Triage

  1. Step 1: Identify all recipients contacted by the flagged sender address. Query EmailEvents for the sender's full communication history with your organization going back 90 days to establish whether this is a new persona or an existing contact that changed behavior.
  2. Step 2: Research the sender account externally. Search the email address across OSINT sources (HaveIBeenPwned, social media, GitHub, LinkedIn). A completely clean footprint on a privacy provider with no prior history targeting multiple employees simultaneously is a strong persona indicator.
  3. Step 3: Inspect email content and attachments. For delivered emails, retrieve the message body and attachment hashes. Submit attachment hashes to VirusTotal. Check URLs in links against threat intelligence. Persona-establishing emails often contain pretext designed to build a relationship (job offers, vendor pitches, conference invitations).
  4. Step 4: Correlate with authentication logs. Query AADSignInLogs for any sign-in attempts using credentials that could be linked to the persona (e.g., if the email impersonates a real vendor, check for authentication attempts from unusual ASNs around the same timeframe).
  5. Step 5: Assess targeting pattern. Determine whether recipients share a common attribute — same department, same project, same access level (e.g., all in finance, all with admin rights). Targeted department clustering suggests reconnaissance-informed persona deployment rather than random spam.
  6. Step 6: Check Defender for Office 365 threat protection for automated classification. Review the Safe Links and Safe Attachments verdicts for any delivered emails from this sender. Determine if ZAP (zero-hour auto purge) retroactively removed any messages.

Containment

  1. If confirmed malicious persona: Block the sender address and sender domain in Exchange Online Protection or the email gateway. Create a transport rule to quarantine future messages matching sender domain with a user-submitted explanation for the security team.
  2. Purge delivered emails: Use the Microsoft 365 Compliance Center Content Search or Security & Compliance PowerShell (Search-Mailbox or New-ComplianceSearchAction -Purge) to soft-delete delivered messages from recipient mailboxes before users interact with them.
  3. Notify targeted recipients: Send a direct communication to all identified recipients explaining they received a suspicious contact attempt. Instruct them not to click links or open attachments from the sender, and to report any follow-up contact.
  4. Enrich threat intelligence: Submit the sender email address, any identified usernames, and associated infrastructure to your SIEM's threat intelligence feed to enable retroactive hunting across historical logs.
  5. If cloud account persona confirmed (T1585.003): Notify affected cloud platform's abuse team (GitHub Security, AWS Abuse, GCP Abuse) with evidence of the suspected malicious account. Document account identifiers for law enforcement referral if warranted.

Evidence Collection

  1. Export complete email headers for all inbound messages from the sender — headers contain originating IP, relay path, and authentication results (SPF, DKIM, DMARC pass/fail) that can fingerprint the sending infrastructure.
  2. Capture full email body and attachment hashes. Store in case management system with chain-of-custody documentation. Note whether DKIM signatures validate (persona accounts on legitimate providers often pass DKIM, which aids delivery).
  3. Query Exchange audit logs (AuditLogs or OfficeActivity) for any mailbox rules created by recipients after receiving the suspicious contact — persona operators may prompt victims to add forwarding rules.
  4. Collect network proxy logs for recipient endpoints showing outbound connections to social media platforms, GitHub, LinkedIn, or other services in the 24-48 hours after email delivery — victims responding to persona contact leave network traces.
  5. Document the sender's registration footprint: when was the account first seen in your email logs, what MX infrastructure was used, and whether the sending IP resolves to a known hosting provider or residential ISP.
  6. If the persona is identified on external platforms (LinkedIn, GitHub, etc.), archive public profile pages using a legal preservation tool before the adversary can delete them.

Escalation Criteria

  • ! Escalate to Incident Response if any targeted recipient clicked links or opened attachments from the persona account — credential harvest or malware delivery may have occurred.
  • ! Escalate if the persona successfully established a communication thread with an employee (reply detected in sent mail logs) — social engineering may be in progress.
  • ! Escalate if the targeting pattern aligns with employees having privileged access (IT admins, finance, C-suite), suggesting the persona campaign is a precursor to BEC, credential phishing, or access broker targeting.
  • ! Escalate if the identified persona email address or infrastructure appears in threat intelligence feeds associated with known APT groups (Kimsuky, Contagious Interview, Fox Kitten) — nation-state personas require immediate executive notification and potential law enforcement contact.
  • ! Escalate if evidence of the persona account is found on code repositories (GitHub, GitLab) that interact with your organization's open source projects — supply chain poisoning via malicious commits may be the objective.

Investigation Guide

Forensic Artifacts

  • > Email headers with originating IP, relay path, and authentication results (SPF/DKIM/DMARC) from all inbound messages from the persona account
  • > Exchange Online audit logs showing message delivery status, ZAP actions, and any mailbox rule creation by targeted recipients
  • > Defender for Office 365 URL detonation reports and Safe Attachments verdicts for emails from the suspected persona
  • > Network proxy/DNS logs from recipient endpoints showing outbound connections following email delivery
  • > Azure AD sign-in logs showing authentication attempts correlated with persona contact timeframes
  • > OfficeActivity logs showing whether any targeted recipients forwarded messages externally or set auto-reply rules after contact

Tuning Guidance

Primary false positive source is legitimate use of privacy email providers by researchers, journalists, vendors, and security professionals. Build an allowlist of known legitimate senders using privacy providers (e.g., established security vendor contacts, known researchers). Tune the TargetedUsers threshold upward (from 2 to 5) in environments with large external-facing teams (sales, HR) who routinely receive unsolicited multi-recipient campaigns. For the risk score, reduce the weight for free providers (Gmail, Outlook, Yahoo) in consumer-oriented businesses where customer contact from free addresses is normal. Suppress alerts for domains that consistently appear in marketing/newsletter pattern with unsubscribe links in body. Consider adding a DMARC alignment check — persona accounts at major providers typically pass DMARC, but DMARC pass from a never-before-seen sender with multi-employee targeting remains suspicious. Calibrate the burst-window threshold (currently 2 hours) based on your organization's normal inbound email volume to avoid alert fatigue from marketing blasts.


Hunting Queries

Hunts for coordinated persona operations where multiple different privacy-provider accounts target the same employee. A single employee receiving contact from 2+ distinct ProtonMail/Tutanota accounts suggests the adversary is cycling personas or testing which establishes rapport.

Hunting — KQL
kql
// Hunt: Detect coordinated multi-sender persona campaigns targeting the same employee cohort
// Different senders, same targets suggest coordinated persona operation
let LookbackDays = 30d;
let TargetCohortSize = 3;
EmailEvents
| where TimeGenerated > ago(LookbackDays)
| where EmailDirection == "Inbound"
| where DeliveryAction in ("Delivered", "Junked")
| extend SenderDomain = tolower(tostring(split(SenderFromAddress, "@")[1]))
| where SenderDomain in~ ("protonmail.com", "proton.me", "tutanota.com", "guerrillamail.com",
    "temp-mail.org", "mailinator.com", "cock.li", "disroot.org")
| summarize 
    UniqueSenders = dcount(SenderFromAddress),
    Senders = make_set(SenderFromAddress, 20),
    EmailCount = count(),
    FirstContact = min(TimeGenerated)
    by RecipientEmailAddress
| where UniqueSenders >= 2
| join kind=inner (
    EmailEvents
    | where TimeGenerated > ago(LookbackDays)
    | where EmailDirection == "Inbound"
    | extend SenderDomain = tolower(tostring(split(SenderFromAddress, "@")[1]))
    | where SenderDomain in~ ("protonmail.com", "proton.me", "tutanota.com")
    | summarize TargetedRecipients = make_set(RecipientEmailAddress)
    by SenderFromAddress
) on $left.Senders contains $right.SenderFromAddress
| where array_length(TargetedRecipients) >= TargetCohortSize
| project FirstContact, RecipientEmailAddress, UniqueSenders, EmailCount, Senders
Hunting — SPL
spl
index=email OR index=mail_logs sourcetype IN ("ms:o365:management", "exchange:message_tracking")
| search direction="inbound"
| eval sender_domain=lower(replace(coalesce(sender, SenderAddress, ""), ".*@", ""))
| where match(sender_domain, "protonmail\.com|proton\.me|tutanota\.com|guerrillamail\.com|temp-mail\.org|mailinator\.com|cock\.li|disroot\.org")
| eval recipient=coalesce(recipient, RecipientAddress, to_address)
| stats
    dc(sender_address) AS unique_senders,
    values(sender_address) AS sender_list,
    count AS email_count,
    min(_time) AS first_contact
    by recipient
| where unique_senders >= 2
| eval first_contact=strftime(first_contact, "%Y-%m-%d %H:%M:%S")
| table first_contact, recipient, unique_senders, email_count, sender_list
| sort - unique_senders

Hunts for corporate endpoints accessing multiple social media or email account registration pages within a short window. While insider threat scenarios are one interpretation, this pattern may also indicate an employee whose device was used to create adversary infrastructure personas, or a compromised endpoint being used for persona creation automation.

Hunting — KQL
kql
// Hunt: Corporate endpoints connecting to social media account registration/management pages
// Identifies employees whose endpoints may be creating or managing external persona accounts
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (80, 443)
| where RemoteUrl has_any (
    "accounts.google.com/signup",
    "signup.live.com",
    "join.yahoo.com",
    "proton.me/mail/signup",
    "protonmail.com/create-account",
    "tutanota.com/signup",
    "accounts.google.com/v3/signin/identifier",
    "linkedin.com/signup",
    "github.com/join",
    "twitter.com/i/flow/signup",
    "facebook.com/r.php"
)
| summarize
    RegistrationAttempts = count(),
    Platforms = make_set(RemoteUrl, 10),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
    by DeviceName, InitiatingProcessAccountName, InitiatingProcessFileName
| where RegistrationAttempts >= 3
| order by RegistrationAttempts desc
Hunting — SPL
spl
index=network OR index=proxy sourcetype IN ("stream:http", "pan:traffic", "bluecoat:proxysg:access:kv", "websense:cg:kv")
| search (url="*signup*" OR url="*register*" OR url="*create-account*" OR url="*join*")
    (url="*protonmail*" OR url="*proton.me*" OR url="*tutanota*" OR url="*accounts.google.com/signup*"
     OR url="*signup.live.com*" OR url="*linkedin.com/signup*" OR url="*github.com/join*"
     OR url="*twitter.com/i/flow/signup*")
| eval src_host=coalesce(src_ip, ClientIP, SourceIP)
| stats
    count AS registration_attempts,
    dc(url) AS unique_platforms,
    values(url) AS platform_urls,
    min(_time) AS first_seen
    by src_host, user
| where registration_attempts >= 3
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S")
| table first_seen, src_host, user, registration_attempts, unique_platforms, platform_urls
| sort - registration_attempts

Correlates inbound persona-attributed emails with subsequent risky authentication attempts against the targeted user's account. Detects the full kill chain: persona establishes contact → victim engages → adversary attempts credential-based access. High-value alert when a user targeted by a ProtonMail/Tutanota sender experiences failed sign-ins within 7 days.

Hunting — KQL
kql
// Hunt: New cloud/SaaS account sign-ins correlated with persona contact timeline
// Identifies whether persona-sourced emails preceded unauthorized cloud account access
let PersonaContactEmails = EmailEvents
    | where TimeGenerated > ago(30d)
    | where EmailDirection == "Inbound"
    | where DeliveryAction == "Delivered"
    | extend SenderDomain = tolower(tostring(split(SenderFromAddress, "@")[1]))
    | where SenderDomain in~ ("protonmail.com", "proton.me", "tutanota.com", "guerrillamail.com")
    | project ContactTime = TimeGenerated, RecipientEmailAddress;
SigninLogs
| where TimeGenerated > ago(30d)
| where ResultType != "0"
| join kind=inner PersonaContactEmails on $left.UserPrincipalName == $right.RecipientEmailAddress
| where TimeGenerated between (ContactTime .. datetime_add("day", 7, ContactTime))
| where RiskLevelDuringSignIn in ("medium", "high")
| summarize
    FailedSignins = count(),
    UniqueIPs = dcount(IPAddress),
    Countries = make_set(LocationDetails, 5),
    FirstAttempt = min(TimeGenerated),
    PersonaContactTime = min(ContactTime)
    by UserPrincipalName, AppDisplayName
| extend DaysAfterContact = datetime_diff("day", FirstAttempt, PersonaContactTime)
| where DaysAfterContact between (0 .. 7)
| order by FailedSignins desc
Hunting — SPL
spl
index=azure sourcetype="azure:aad:signin"
| eval upn=coalesce(userPrincipalName, UserId)
| eval result=coalesce(resultType, status.errorCode, "0")
| where result!="0"
| eval signin_time=_time
| join type=inner upn [
    index=email sourcetype="ms:o365:management"
    | search Operation="Receive"
    | eval sender_domain=lower(replace(SenderAddress, ".*@", ""))
    | where match(sender_domain, "protonmail\.com|proton\.me|tutanota\.com")
    | eval contact_time=_time
    | eval recipient=coalesce(RecipientAddress, Recipient)
    | rename recipient AS upn
    | table upn, contact_time
]
| where signin_time > contact_time AND signin_time < (contact_time + 604800)
| stats
    count AS failed_signins,
    dc(IPAddress) AS unique_ips,
    min(signin_time) AS first_attempt,
    min(contact_time) AS persona_contact_time
    by upn, AppDisplayName
| eval days_after_contact=round((first_attempt - persona_contact_time) / 86400, 1)
| where days_after_contact >= 0 AND days_after_contact <= 7
| table upn, AppDisplayName, failed_signins, unique_ips, days_after_contact
| sort - failed_signins

Atomic Red Team Tests

Test 1 Simulate Persona-Based Inbound Email Campaign from Privacy Provider
windows

Validates that the EmailEvents-based detection fires when multiple employees receive inbound messages from a ProtonMail/Tutanota address. Uses PowerShell to confirm email telemetry is being ingested and the alert logic triggers at the expected thresholds.

Command

powershell
# Prerequisite: Exchange Online PowerShell module, admin credentials
# Step 1: Confirm EmailEvents are flowing for a test privacy-provider sender
Connect-ExchangeOnline -UserPrincipalName [email protected]

# Step 2: Query recent inbound emails from privacy providers to validate telemetry
Get-MessageTrace -SenderAddress '*@protonmail.com' -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) | Select-Object Received, SenderAddress, RecipientAddress, Subject, Status | Format-Table

# Step 3: Simulate detection query logic against Message Trace
$privacyDomains = @('protonmail.com','proton.me','tutanota.com','guerrillamail.com')
$messages = Get-MessageTrace -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) | Where-Object { $_.SenderAddress -match ($privacyDomains -join '|') }
$grouped = $messages | Group-Object SenderAddress | Where-Object { ($_.Group | Select-Object -ExpandProperty RecipientAddress -Unique).Count -ge 2 }
$grouped | Select-Object Name, Count, @{N='UniqueRecipients';E={($_.Group | Select-Object -ExpandProperty RecipientAddress -Unique).Count}} | Format-Table

Cleanup

powershell
Disconnect-ExchangeOnline -Confirm:$false

Expected Telemetry

EmailEvents table in Microsoft Defender for Office 365 should show matching records; Message Trace output confirms telemetry is flowing for privacy-provider senders

Expected Detection

Detection query should return the test sender when 2+ unique recipients have been contacted; risk score calculation should produce >= 25 for multi-recipient privacy-provider contact

Test 2 Test Network Detection for Social Media Account Registration Activity
windows

Validates that endpoint network telemetry captures connections to social media signup pages. Simulates the network behavior of persona account establishment from a corporate endpoint by making controlled connections to registration endpoint paths.

Command

powershell
# Test DNS and HTTP connection telemetry for account registration endpoints
# This simulates the network footprint of persona account creation activity

# Step 1: Generate DNS queries for account registration domains (observe in Sysmon Event 22)
$registrationDomains = @(
    'accounts.google.com',
    'proton.me',
    'signup.live.com',
    'join.yahoo.com'
)

foreach ($domain in $registrationDomains) {
    Write-Host "[*] Resolving $domain"
    Resolve-DnsName -Name $domain -Type A -ErrorAction SilentlyContinue | Select-Object -First 1
    Start-Sleep -Milliseconds 500
}

# Step 2: Make HTTP HEAD requests to registration paths (generates DeviceNetworkEvents)
# Use Invoke-WebRequest with -Method HEAD to avoid actually loading pages
$registrationUrls = @(
    'https://accounts.google.com/signup',
    'https://proton.me/mail/signup'
)

foreach ($url in $registrationUrls) {
    Write-Host "[*] Testing connectivity to: $url"
    try {
        Invoke-WebRequest -Uri $url -Method HEAD -TimeoutSec 5 -ErrorAction Stop | Select-Object StatusCode
    } catch {
        Write-Host "    Connection attempt recorded (status: $($_.Exception.Message))"
    }
    Start-Sleep -Seconds 1
}

Write-Host "[*] Test complete. Review DeviceNetworkEvents and Sysmon Event 22 for DNS/connection telemetry."

Cleanup

powershell
# No persistent changes made; DNS cache can be cleared if needed
ipconfig /flushdns

Expected Telemetry

Sysmon Event ID 22 (DNS Query) for registration domains; DeviceNetworkEvents ConnectionSuccess/ConnectionAttempted events for HTTPS connections to signup paths

Expected Detection

Hunting query for corporate endpoints connecting to social media registration pages should return this test device after 3+ registration URL accesses are observed

Test 3 Simulate Cloud Account Creation for Persona Infrastructure (Azure CLI)
linux

Validates detection of cloud account establishment activity by simulating T1585.003 (Cloud Accounts) — creating a test service principal or guest account that mimics adversary persona account creation in cloud infrastructure. Requires Azure subscription access.

Command

bash
#!/bin/bash
# Prerequisite: Azure CLI installed and authenticated (az login)
# This simulates T1585.003 Cloud Account establishment patterns

# Step 1: Create a test guest user (persona account simulation)
TEST_PERSONA_EMAIL="test-persona-detection-$(date +%s)@outlook.com"
TEST_PERSONA_DISPLAY="Test Persona Account Detection"

echo "[*] Simulating cloud persona account invitation (T1585.003)"
az ad user invite --email "$TEST_PERSONA_EMAIL" --display-name "$TEST_PERSONA_DISPLAY" 2>/dev/null \
    && echo "[+] Guest invitation sent - check AuditLogs for InviteExternalUser operation" \
    || echo "[!] Invitation failed (may need permissions) - checking alternative method"

# Step 2: Create a test app registration (persona service account pattern)
TEST_APP_NAME="test-detection-persona-app-$(date +%s)"
echo "[*] Creating test app registration to simulate persona service account"
APP_ID=$(az ad app create --display-name "$TEST_APP_NAME" --query appId -o tsv 2>/dev/null)
if [ -n "$APP_ID" ]; then
    echo "[+] App registration created: $APP_ID"
    echo "[+] This should generate AuditLogs entry: Operation=Add application, Category=ApplicationManagement"
fi

# Step 3: Query AuditLogs to confirm telemetry captured
echo "[*] Querying Azure Audit Logs for persona account creation events..."
az monitor activity-log list \
    --start-time $(date -u -d '10 minutes ago' +%Y-%m-%dT%H:%M:%SZ) \
    --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
    --query "[?operationName.localizedValue=='Create user' || operationName.localizedValue=='Invite external user' || operationName.localizedValue=='Add application'].{time:eventTimestamp, operation:operationName.localizedValue, caller:caller}" \
    -o table 2>/dev/null || echo "[!] Activity log query requires additional permissions"

Cleanup

bash
# Clean up test app registration
if [ -n "$APP_ID" ]; then
    az ad app delete --id "$APP_ID"
    echo "[*] Test app registration deleted: $APP_ID"
fi

Expected Telemetry

AuditLogs in Azure AD / Microsoft Sentinel: Operation=Add application or Invite external user, Category=ApplicationManagement or UserManagement. CloudAppEvents table should show account creation activity.

Expected Detection

T1585.003 sub-technique hunting queries targeting cloud account establishment should surface the test app registration and guest invitation events from AuditLogs within 5-10 minutes of creation

Related Detections