Back to Intelligence

UAT-11587 Antino Backdoor Turns Microsoft 365 Into a C2 Channel — Detection and Hardening Guide for Defenders

SA
Security Arsenal Team
October 4, 2026
12 min read

Cisco Talos has published a detailed account of UAT-11587, a China-linked espionage cluster tracked since September 2025, which by July 2026 had compromised at least 16 government and policy organizations across eight Asian countries. The campaign's defining characteristic is a backdoor Talos calls Antino, which doesn't beacon to a disposable attacker-controlled domain. Instead, it uses the victim's own Microsoft 365 tenant — Exchange Online mailboxes and Microsoft Graph — as its command-and-control (C2) channel.

This is the defensive nightmare scenario for network-centric SOC teams. C2 traffic rides on legitimate TLS sessions to graph.microsoft.com and outlook.office365.com, blends into sanctioned SaaS traffic, and bypasses domain-reputation blocking entirely. If your detection strategy still leans on egress domain blocklists, you are blind to this class of implant.

This post breaks down how the Antino/M365-as-C2 tradecraft works from a defender's perspective, and delivers concrete hunting content — Sigma, KQL, and Velociraptor VQL — plus tenant hardening steps you can implement this week.

Technical Analysis

Threat Actor and Targeting

  • Actor: UAT-11587 (Talos internal designator), assessed as China-linked with moderate-to-high confidence based on targeting, tooling lineage, and operational tempo.
  • Victims: At least 16 government and public-policy organizations across eight Asian nations — ministries, diplomatic entities, and policy bodies. Espionage objective: persistent collection of diplomatic and policy communications.
  • Active window: September 2025 through at least July 2026 — confirmed active, in-the-wild exploitation, not theoretical.

How the Attack Works (Defender's View)

Based on Talos's reporting, the Antino intrusion chain has three defensible choke points:

1. Initial access and staging. UAT-11587 gains a foothold through targeted social engineering and exploitation of exposed services, then drops the Antino implant — a backdoor engineered specifically for low-and-slow espionage rather than smash-and-grab operations.

2. C2 over Microsoft 365. This is the core innovation defenders must understand. Rather than connecting to attacker infrastructure, Antino:

  • Authenticates to the victim's own (or an attacker-controlled but victim-adjacent) M365 tenant using stolen or consented OAuth tokens / app credentials.
  • Reads tasking from email messages placed in specific mailbox folders (drafts, deleted items, or dedicated folders), typically via Microsoft Graph API calls or Exchange Web Services.
  • Exfiltrates collected data by writing to mailbox items, drafts, or attachments — meaning stolen data transits Microsoft's infrastructure, not a suspicious external IP.

From a network sensor's perspective, the implant looks like an Outlook client. The traffic is HTTPS to Microsoft-owned IP space with valid certificates. Beaconing intervals are long and jittered, mimicking normal mail sync patterns.

3. Persistence and token abuse. Because access is brokered through OAuth grants and app registrations, the actor survives password resets and MFA enforcement on the compromised user account. Expect to find:

  • Illicit consent grants to app registrations with Mail.Read, Mail.ReadWrite, Mail.Send, or offline_access scopes.
  • Suspicious inbox rules created to hide or auto-route tasking/response mail (a hallmark of M365 C2 tradecraft).
  • Non-interactive sign-ins from unusual geographies or ASNs against the compromised mailbox.

Affected Products and Platforms

  • Microsoft 365 / Office 365 tenants (Exchange Online, Microsoft Graph)
  • Windows endpoints hosting the Antino implant
  • Any organization with federated M365 and insufficient OAuth app governance — government and policy organizations are the observed target set, but the technique is tenant-agnostic

Exploitation status: Confirmed active exploitation by a nation-state-aligned actor. No CVE is associated with this campaign — it abuses legitimate platform functionality (living-off-the-land at the SaaS layer). It does not currently appear in CISA KEV because there is no patchable vulnerability; the fix is architectural and procedural.

Detection & Response

The central detection problem: separating malicious Graph/Exchange API consumption from legitimate client behavior. The most reliable signals are (a) which process on the endpoint is talking to M365 API endpoints, (b) which OAuth grants exist in the tenant, and (c) what non-interactive mailbox access patterns look like.

Sigma Rules

The highest-fidelity endpoint signal is a non-Office process establishing connections to Microsoft Graph/Exchange API endpoints — Antino is not Outlook, and it has no business doing so. The second rule catches inbox-rule-based concealment, a well-documented M365 C2 companion behavior, from Office 365 audit logs.

YAML
---
title: Non-Office Process Connecting to Microsoft Graph or Exchange Online Endpoints
id: 4a9e2c17-8b3d-4f56-a291-7c1e5d8f2034
status: experimental
description: Detects network connections to Microsoft Graph or Exchange Online API endpoints from processes that are not legitimate Microsoft 365 clients. Consistent with implants such as the UAT-11587 Antino backdoor using M365 as a C2 channel.
references:
  - https://securityaffairs.com/200264/apt/antino-backdoor-uses-your-inbox-as-its-control-panel.html
  - https://attack.mitre.org/techniques/T1102/002/
  - https://attack.mitre.org/techniques/T1071/001/
author: Security Arsenal
date: 2026/07/15
tags:
  - attack.command_and_control
  - attack.t1102.002
  - attack.t1071.001
logsource:
  category: network_connection
  product: windows
detection:
  selection:
    DestinationHostname|contains:
      - 'graph.microsoft.com'
      - 'outlook.office365.com'
      - 'outlook.office.com'
      - 'substrate.office.com'
  filter_known_clients:
    Image|endswith:
      - '\OUTLOOK.EXE'
      - '\MicrosoftTeams.exe'
      - '\ms-teams.exe'
      - '\OneDrive.exe'
      - '\lync.exe'
      - '\msedge.exe'
      - '\chrome.exe'
      - '\firefox.exe'
      - '\iexplore.exe'
      - '\WINWORD.EXE'
      - '\EXCEL.EXE'
      - '\POWERPNT.EXE'
      - '\SearchProtocolHost.exe'
      - '\msteams.exe'
      - '\PhoneExperienceHost.exe'
      - '\Microsoft.Office.Outlook.Hub.exe'
  condition: selection and not filter_known_clients
falsepositives:
  - Legitimate line-of-business applications integrating with Graph API (validate per-app)
  - EDR and email security tooling polling mailboxes
  - PowerShell/Graph SDK administration by IT staff (tune by process path and user)
level: high
---
title: Suspicious Inbox Rule Creation Indicating Mail Concealment or C2 Staging
id: 8d3b5f90-2c47-4e81-b6a3-9f0d2e7c4156
status: experimental
description: Detects creation of Exchange inbox rules that delete, move to obscure folders, or mark-as-read incoming mail — a technique used by actors like UAT-11587 to hide C2 tasking and exfiltration traffic from the mailbox owner.
references:
  - https://securityaffairs.com/200264/apt/antino-backdoor-uses-your-inbox-as-its-control-panel.html
  - https://attack.mitre.org/techniques/T1098/002/
  - https://attack.mitre.org/techniques/T1114/002/
author: Security Arsenal
date: 2026/07/15
tags:
  - attack.persistence
  - attack.t1098.002
  - attack.collection
  - attack.t1114.002
logsource:
  product: m365
  service: exchange
detection:
  selection:
    Operation:
      - 'New-InboxRule'
      - 'Set-InboxRule'
    Parameters|contains:
      - 'DeleteMessage'
      - 'MoveToFolder'
      - 'MarkAsRead'
      - 'SoftDeleteMessage'
      - 'PermanentDelete'
  condition: selection
falsepositives:
  - Users creating legitimate mail hygiene rules (baseline per-user rule creation rates)
  - Help desk automation creating rules during migrations
level: medium
---
title: Non-Interactive Sign-In to Exchange Online From Unusual Process Pattern
id: 2f7a1d34-6e90-4b28-c845-3a1d9e6b7520
status: experimental
description: Detects non-interactive (client credential / refresh token) authentication to Exchange Online or Microsoft Graph, a pattern consistent with OAuth token abuse by implants using M365 as C2. Tune against known service principals.
references:
  - https://securityaffairs.com/200264/apt/antino-backdoor-uses-your-inbox-as-its-control-panel.html
  - https://attack.mitre.org/techniques/T1550/001/
  - https://attack.mitre.org/techniques/T1528/
author: Security Arsenal
date: 2026/07/15
tags:
  - attack.credential_access
  - attack.t1528
  - attack.t1550.001
logsource:
  product: azure
  service: signinlogs
detection:
  selection:
    resourceDisplayName|contains:
      - 'Microsoft Graph'
      - 'Office 365 Exchange Online'
    isInteractive: false
  filter_known_spn:
    appDisplayName|contains:
      - 'Exchange Online Protection'
      - 'Microsoft '
      - 'Office 365 '
  condition: selection and not filter_known_spn
falsepositives:
  - Legitimate third-party mail hygiene, archiving, and backup services (allowlist by appId after verification)
  - Internal automation service principals
level: high

KQL — Microsoft Sentinel / Defender

This hunt runs against Defender for Endpoint telemetry and surfaces unknown processes communicating with M365 API endpoints. The allowlist approach is deliberate: every additional exclusion is a decision you make consciously, and anything left standing deserves analyst review. A companion query hunts the mailbox-audit side for tasking-pattern reads (repeated reads of a small set of folders by a single non-interactive session).

KQL — Microsoft Sentinel / Defender
// Hunt: unknown processes connecting to Microsoft Graph / Exchange Online API endpoints
// Use case: UAT-11587 Antino backdoor C2 over M365 (T1102.002)
let KnownClients = dynamic([
    "OUTLOOK.EXE", "ms-teams.exe", "MicrosoftTeams.exe", "OneDrive.exe",
    "lync.exe", "msedge.exe", "chrome.exe", "firefox.exe",
    "WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE", "SearchProtocolHost.exe",
    "PhoneExperienceHost.exe"
]);
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where RemoteUrl has_any ("graph.microsoft.com", "outlook.office365.com", "outlook.office.com", "substrate.office.com")
| where InitiatingProcessFileName !in~ (KnownClients)
| summarize
    ConnectionCount = count(),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated),
    RemoteUrls = make_set(RemoteUrl, 20),
    RemoteIPs = make_set(RemoteIP, 20),
    Accounts = make_set(InitiatingProcessAccountName, 5)
    by DeviceName, InitiatingProcessFileName, InitiatingProcessFolderPath, InitiatingProcessCommandLine
| where ConnectionCount > 20  // sustained beaconing/sync pattern, not a one-off
| order by FirstSeen asc;
KQL — Microsoft Sentinel / Defender
// Hunt: non-interactive Graph/Exchange sign-ins by unusual applications
// Use case: OAuth token abuse for mailbox-as-C2 (T1528 / T1550.001)
SigninLogs
| where TimeGenerated > ago(14d)
| where ResourceDisplayName has_any ("Microsoft Graph", "Office 365 Exchange Online")
| where IsInteractive == false
| where AppDisplayName !startswith "Microsoft" and AppDisplayName !startswith "Office 365"
| summarize
    SigninCount = count(),
    SourceIPs = make_set(IPAddress, 10),
    Locations = make_set(Location, 10),
    Users = make_set(UserPrincipalName, 10)
    by AppId, AppDisplayName
| order by SigninCount desc;
KQL — Microsoft Sentinel / Defender
// Hunt: inbox rule creation with concealment actions (Office 365 audit)
// Use case: hiding C2 tasking mail from mailbox owner (T1098.002)
OfficeActivity
| where TimeGenerated > ago(30d)
| where Operation in~ ("New-InboxRule", "Set-InboxRule")
| where Parameters has_any ("DeleteMessage", "MarkAsRead", "MoveToFolder", "PermanentDelete")
| project TimeGenerated, UserId, ClientIP, Operation, Parameters, OfficeWorkload
| order by TimeGenerated desc;

Velociraptor VQL

Use this artifact across the fleet to identify any process holding an active or recently-closed connection to M365 API endpoints that isn't a sanctioned client — ideal for rapid triage when you suspect an implant is mid-beacon.

VQL — Velociraptor
-- Hunt: non-Office processes with connections to Microsoft 365 API endpoints
-- Use case: UAT-11587 Antino backdoor C2-over-M365 (T1102.002)
LET known_clients = ("outlook.exe", "ms-teams.exe", "microsoftteams.exe",
    "onedrive.exe", "lync.exe", "msedge.exe", "chrome.exe",
    "firefox.exe", "winword.exe", "excel.exe", "powerpnt.exe")

SELECT
    Pid,
    Name,
    CommandLine,
    Exe,
    Username,
    netstat().RemoteIP AS RemoteIP,
    netstat().RemotePort AS RemotePort,
    netstat().Status AS ConnStatus
FROM pslist()
WHERE netstat().RemotePort = 443
  AND lower(Name) NOT IN known_clients
  AND (
        netstat().RemoteIP =~ '^13\.107\.'      // Microsoft 365 CDN/API ranges
     OR netstat().RemoteIP =~ '^40\.1(2[6-9]|3[0-9])\.'
     OR netstat().RemoteIP =~ '^52\.9[6-9]\.'
     OR netstat().RemoteIP =~ '^52\.10[0-9]\.'
  )

Note on IP ranges: Microsoft 365 endpoint ranges change. Pull the current optimize/allow endpoint sets from the official Microsoft 365 URLs and IP address ranges JSON feed and update the regex accordingly, or enrich via DNS resolution in a follow-up query against the process's connection history.

Remediation / Hardening Script

There is no patch for this campaign — the fix is OAuth governance and mailbox-audit hygiene. The following PowerShell (requires the Microsoft.Graph and ExchangeOnlineManagement modules, run by a Global/Cloud Application Admin) audits the two persistence mechanisms Antino-style tradecraft depends on: over-privileged app consents and concealment inbox rules.

PowerShell
# UAT-11587 / M365-as-C2 Tenant Audit Script
# Run as: Global Administrator or Cloud Application Administrator
# Requires: Microsoft.Graph, ExchangeOnlineManagement modules

Connect-MgGraph -Scopes "Application.Read.All","AuditLog.Read.All","Directory.Read.All"
Connect-ExchangeOnline

# --- 1. Find service principals with high-risk mail scopes ---
$ riskyScopes = @("Mail.Read","Mail.ReadWrite","Mail.Send","Mail.ReadBasic.All",
                  "MailboxSettings.ReadWrite","full_access_as_app")
Write-Host "`n=== Service Principals with High-Risk Mail Scopes ===" -ForegroundColor Cyan
$spns = Get-MgServicePrincipal -All
foreach ($spn in $spns) {
    $assignments = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $spn.Id -ErrorAction SilentlyContinue
    foreach ($a in $assignments) {
        $resource = Get-MgServicePrincipal -ServicePrincipalId $a.ResourceId -ErrorAction SilentlyContinue
        $role = $resource.AppRoles | Where-Object { $_.Id -eq $a.AppRoleId }
        if ($riskyScopes -contains $role.Value) {
            [PSCustomObject]@{
                AppName      = $spn.DisplayName
                AppId        = $spn.AppId
                Scope        = $role.Value
                Resource     = $resource.DisplayName
                CreatedDate  = $spn.AdditionalProperties['createdDateTime']
            } | Format-Table -AutoSize
        }
    }
}

# --- 2. Enumerate user-delegated OAuth consent grants ---
Write-Host "`n=== Delegated OAuth Grants with Mail Permissions ===" -ForegroundColor Cyan
$grants = Get-MgOauth2PermissionGrant -All
$grants | Where-Object { $_.Scope -match "Mail\.|MailboxSettings" } |
    Select-Object ClientId, ConsentType, Scope |
    Format-Table -AutoSize

# --- 3. Hunt concealment inbox rules across all mailboxes ---
Write-Host "`n=== Inbox Rules with Delete/Hide/Move Actions ===" -ForegroundColor Cyan
$mailboxes = Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox
foreach ($mbx in $mailboxes) {
    $rules = Get-InboxRule -Mailbox $mbx.UserPrincipalName -ErrorAction SilentlyContinue
    foreach ($rule in $rules) {
        if ($rule.DeleteMessage -or $rule.MarkAsRead -or
            $rule.MoveToFolder -match "RSS|Deleted|Junk|Archive|Recoverable" -or
            $rule.RedirectTo -or $rule.ForwardTo) {
            [PSCustomObject]@{
                Mailbox      = $mbx.UserPrincipalName
                RuleName     = $rule.Name
                Delete       = $rule.DeleteMessage
                MarkAsRead   = $rule.MarkAsRead
                MoveTo       = $rule.MoveToFolder
                RedirectTo   = $rule.RedirectTo
                ForwardTo    = $rule.ForwardTo
            } | Format-Table -AutoSize
        }
    }
}

# --- 4. Verify Unified Audit Log is enabled (required for detection) ---
Write-Host "`n=== Audit Log Status ===" -ForegroundColor Cyan
Get-AdminAuditLogConfig | Select-Object UnifiedAuditLogIngestionEnabled

Write-Host "`nAudit complete. Review every object above: Antino-style tradecraft persists via consented apps and inbox rules, which survive password resets and MFA." -ForegroundColor Yellow

Remediation

Because this campaign abuses legitimate M365 functionality rather than a patchable vulnerability, remediation is architectural. Prioritize in this order:

  1. Revoke illicit OAuth grants immediately. For any suspicious app registration or consent grant identified by the audit script, remove the grant, delete the service principal, and rotate credentials for every account that consented. Assume refresh tokens are compromised — revocation alone is insufficient; disable and re-provision the affected app registration.

  2. Enforce admin consent workflows. In Entra ID, set user consent to "Do not allow user consent" or restrict it to low-risk, verified-publisher permissions only. Require administrator approval for any scope touching Mail.*, Sites.*, or Files.*. This single control would have blunted the persistence mechanism used here.

  3. Enable and retain Unified Audit Logging + Mailbox Auditing. Confirm UnifiedAuditLogIngestionEnabled = True and per-mailbox auditing is on (it is by default in current tenants, but verify — especially MailItemsAccessed events, which require E5/A5/G5 and are the only reliable way to see what mail an implant read). Ingest these into Sentinel via the Office 365 connector.

  4. Deploy Conditional Access to constrain token use. Require compliant device + approved client app for Exchange Online and Graph access. Block legacy authentication entirely at the tenant level. For service principals, scope access with Conditional Access for workload identities where licensed.

  5. Baseline your sanctioned Graph-integrated applications. The endpoint detection above only works if you know which line-of-business apps legitimately call Graph. Build the inventory now, document business owners, and alert on net-new Graph callers.

  6. Hunt, don't just block. Run the KQL and VQL content across at least 30 days of history. Espionage actors dwell for months — UAT-11587 operated for ~10 months before public disclosure. If you find suspicious non-interactive Graph sessions or concealment inbox rules, treat it as an IR event: isolate the endpoint, revoke all sessions (Revoke-MgUserSignInSession), preserve mailbox audit data, and scope laterally.

  7. Government/policy organizations: assume elevated targeting. Review Talos's full report for IOCs and TTP specifics, and align your monitoring to the eight-country targeting pattern if your organization operates in or partners with the affected region.

The strategic lesson: SaaS is now a C2 substrate. Your egress filtering strategy must evolve from "block bad domains" to "understand which processes, identities, and app registrations are talking to the good ones."

Related Resources

Security Arsenal Incident Response Services AlertMonitor Platform Book a SOC Assessment incident-response Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.