T1585 Splunk · SPL

Detect Establish Accounts in Splunk

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.

MITRE ATT&CK

Tactic
Resource Development
Technique
T1585 Establish Accounts
Canonical reference
https://attack.mitre.org/techniques/T1585/

SPL Detection Query

Splunk (SPL)
spl
index=email OR index=mail_logs sourcetype IN ("ms:o365:management", "exchange:message_tracking", "postfix:syslog", "proofpoint:mail")
| search direction="inbound" OR MessageDirection="Inbound" OR message_direction="inbound"
| eval sender_address=coalesce(sender, SenderAddress, from_address, "unknown")
| eval sender_domain=lower(replace(sender_address, ".*@", ""))
| eval is_privacy_provider=if(match(sender_domain, "protonmail\.com|proton\.me|tutanota\.com|tutamail\.com|cock\.li|disroot\.org|riseup\.net|mailfence\.com|guerrillamail\.com|temp-mail\.org|mailinator\.com|yopmail\.com"), 1, 0)
| eval is_free_provider=if(match(sender_domain, "gmail\.com|yahoo\.com|hotmail\.com|outlook\.com|live\.com|icloud\.com|aol\.com"), 1, 0)
| where is_privacy_provider=1 OR is_free_provider=1
| eval recipient=coalesce(recipient, RecipientAddress, to_address, "unknown")
| eval has_attachment=if(match(coalesce(attachment_names, AttachmentNames, ""), ".+"), 1, 0)
| eval has_link=if(match(coalesce(url_count, UrlCount, "0"), "[1-9]"), 1, 0)
| eval delivery_status=coalesce(DeliveryAction, delivery_action, MessageStatus, "unknown")
| stats
    count AS email_count,
    dc(recipient) AS targeted_users,
    values(recipient) AS recipient_list,
    sum(has_attachment) AS attachment_emails,
    sum(has_link) AS link_emails,
    values(subject) AS sample_subjects,
    min(_time) AS first_contact,
    max(_time) AS last_contact,
    max(is_privacy_provider) AS is_privacy_provider
    by sender_address, sender_domain
| eval campaign_duration_hours=round((last_contact - first_contact) / 3600, 1)
| eval risk_score=0
| eval risk_score=risk_score + case(targeted_users >= 10, 40, targeted_users >= 5, 25, targeted_users >= 2, 10, true(), 0)
| eval risk_score=risk_score + case(is_privacy_provider=1, 25, targeted_users >= 3, 15, true(), 0)
| eval risk_score=risk_score + case(attachment_emails >= 3, 20, attachment_emails >= 1, 10, true(), 0)
| eval risk_score=risk_score + case(link_emails >= 5 AND attachment_emails=0, 15, link_emails >= 2, 8, true(), 0)
| eval risk_score=risk_score + case(email_count >= 5 AND campaign_duration_hours <= 2, 15, true(), 0)
| where risk_score >= 25
| eval first_contact_time=strftime(first_contact, "%Y-%m-%d %H:%M:%S")
| eval last_contact_time=strftime(last_contact, "%Y-%m-%d %H:%M:%S")
| table first_contact_time, sender_address, sender_domain, is_privacy_provider, email_count, targeted_users, recipient_list, attachment_emails, link_emails, campaign_duration_hours, sample_subjects, risk_score
| sort - risk_score
medium severity medium confidence

Detects inbound email campaigns from privacy-focused or free email providers targeting multiple internal recipients. Correlates sender domain type, recipient count, attachment/link presence, and burst timing to score persona-based contact campaigns consistent with T1585 account establishment precursor activity.

Data Sources

Microsoft 365 Management LogsExchange Message TrackingProofpoint Email Gateway

Required Sourcetypes

ms:o365:managementexchange:message_tracking

False Positives & Tuning

  • Legitimate bulk notifications from SaaS vendors or third-party services using free email infrastructure
  • Job applicants or external collaborators contacting multiple employees from personal Gmail/Yahoo accounts
  • Security awareness testing platforms sending simulated phishing from free email domains
  • Open source community contributors using ProtonMail contacting engineering teams about vulnerability disclosures

Other platforms for T1585


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 1 Simulate 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 2 Test 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 3 Simulate 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

Related Techniques

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