Report an Incident Become a Partner Careers Contact
Book a Demo
AI Driven Security Operations

Seven Minutes, 100 Storage Accounts: What Agentic Attackers Mean For Your SOC

Adam Jones · CTO & Co-Founder 7 October 2026 7 min read
A timeline comparing a long purple bar for roughly 15 hours 30 minutes of reconnaissance with a thin red sliver for 7 minutes, zoomed into a burst of red bars representing 100+ storage deletion attempts, beside the headline "Recon: 15 hours. Damage: 7 minutes."

In June, two stolen Azure service principals were used to make more than 100 attempts to delete storage accounts in about seven minutes. Key Vaults, Function Apps and App Service plans went the same way, and backup protection locks came under attack. Microsoft tracks the actor as Storm-3168 and calls the operation agentic-driven. The seven minutes made the headlines. The number I think every SOC leader should be looking at is fifteen and a half hours.

What actually happened

Microsoft's write-up, published on 25 September, is unusually precise about timing, and the timing is the story.

  • The way in was a GitHub issue. A service principal's client ID, secret and tenant ID had been pasted into a public issue. Someone later edited it out, but the secret stayed in the issue's edit history and was never rotated. Removing a secret from view does not revoke it.
  • Reconnaissance took about 15 hours and 30 minutes. One service principal enumerated subscriptions, resource groups, virtual machines and resources, with more than 300 successful read operations.
  • The handover took under a second. Seventy seconds after its last inventory call, the first identity tried a ListKeys operation against a storage account that didn't exist. Less than a second after that failed, the second service principal began its destructive run.
  • The destruction took about seven minutes for the 100+ storage account deletions, inside roughly 35 minutes of destructive and credential-collection activity overall, including 30+ successful ListKeys requests for storage access keys.

Microsoft's conclusion: the timing, the division of work across two identities and the overlapping token streams "strongly indicates automated or scripted execution." The Cloud Security Alliance's analysis puts it more bluntly: a sub-second gap between a failed call and the next phase is "far too short to reflect a human operator reviewing output."

The seven minutes is not your window

Ask most security teams how fast they respond and you will get an honest answer in tens of minutes or hours: time to triage, time to pick the alert up, time to work out what it means, time to find someone with permission to act. Set that against seven minutes and the conclusion is obvious and slightly hopeless. No human-paced SOC was ever going to stop the deletion phase once it started.

That is the wrong comparison. The destructive phase is the end of the attack, not the attack. Before it there were fifteen and a half hours in which a service principal that normally does one narrow job was enumerating an entire tenant from somewhere new. That is the window. The question isn't whether your SOC could react inside seven minutes. It's whether anything noticed during those fifteen hours, and whether someone could make a decision about it before the second identity started work.

Agentic attackers compress the end of the kill chain more than the start. Discovery still takes time, because it has to read the environment before it can act on it. The defender's job is to win that earlier, slower phase, because the later one is already lost.

Why the recon phase gets missed

Three reasons, all fixable.

The reads aren't where people look

The Azure Activity Log records write, delete and action operations. It does not record ordinary read (GET) operations. A team whose cloud detection is built on the Activity Log alone would have seen nothing of 300+ reads, only the ListKeys calls and the deletes, which is to say only the ending. Control-plane reads are visible to Microsoft Defender for Resource Manager, which is one reason Microsoft's first recommendation is to turn on the relevant Defender for Cloud plans.

Non-human identities have no "normal" anyone has written down

We have spent a decade building behavioural baselines for people: where they sign in from, which devices, which hours. Service principals rarely get the same treatment, even though a well-behaved one is far more predictable than any human. It authenticates from the same few addresses and calls the same few APIs, day after day. That predictability makes deviation easy to detect, if anyone is looking.

"New IP for a service principal" is a low-severity alert

On its own it is. One anomalous sign-in for an automation identity rarely survives triage in a busy queue. Taken together with what that identity did next, hundreds of reads across subscriptions it never touches, it is a high-confidence incident. Whether those two facts get joined up depends on whether the investigation has time to keep going after the first plausible answer.

Where to start looking

Two Microsoft Sentinel starting points. Both need tuning for your environment.

Service principals signing in successfully from an IP address they haven't used in the previous 30 days:

let known = AADServicePrincipalSignInLogs
    | where TimeGenerated between (ago(31d) .. ago(1d))
    | where ResultType == 0
    | distinct ServicePrincipalId, IPAddress;
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(1d)
| where ResultType == 0
| join kind=leftanti known on ServicePrincipalId, IPAddress
| summarize FirstSeen = min(TimeGenerated), SignIns = count(),
            Resources = make_set(ResourceDisplayName, 10)
          by ServicePrincipalName, ServicePrincipalId, IPAddress

A single caller issuing a burst of key-listing or delete operations, which in this attack was the end of the chain and is the last chance to contain it:

AzureActivity
| where TimeGenerated > ago(1d)
| where OperationNameValue has_any ("LISTKEYS/ACTION", "/DELETE")
| summarize Ops = count(), Resources = dcount(_ResourceId),
            Operations = make_set(OperationNameValue, 10)
          by Caller, CallerIpAddress, bin(TimeGenerated, 10m)
| where Resources >= 10
| order by Ops desc

What held, and why it matters more than detection

The most useful part of Microsoft's report is what didn't fall. Storage accounts protected by resource locks or deletion protection survived. Every attempt against Azure Site Recovery and Azure Backup protection locks failed. The compromised identities held Contributor-level roles, and those roles cannot remove locks.

Read that as a design principle. The controls that held were not the fastest detections. They were permission boundaries set months earlier by someone who assumed an identity might one day be compromised. That leaves three things to do this quarter:

  1. Lock what you can't afford to lose. Production storage, Key Vaults and backup vaults. A lock costs nothing until the day it matters.
  2. Scope every service principal to its job. If an automation identity's task is writing to one container, Contributor on a subscription is an incident waiting to happen.
  3. Treat any exposed secret as compromised. Even if it was deleted within the minute, even if the repository is private now. Rotate it, then check what it did while it was out.

What this means for how SOCs work

I don't think the lesson of Storm-3168 is that defenders need their own fully autonomous agents fighting the attacker's at machine speed. It is that the slow, expensive part of a SOC, the investigation, has to fit inside the attacker's reconnaissance window, not trail behind their impact.

That is the problem we built CYBERSHIELD AI around. Our Investigation Agent works an alert to a verdict in an average of 3m 30s, or 7m 50s when the incident needs Advanced Investigation, where it forms hypotheses and tests them against the estate rather than stopping at the first plausible answer. That second pass is what links a low-severity "new IP for a service principal" to the 300 reads that followed it.

What it doesn't do is take the decision away from people. Whether to close or escalate is set by policy and the customer's own decision templates, not by the model. On our managed service, a senior analyst signs off the verdict, and our SOCs are manned 24/7. Autonomy is configurable, per agent and per tenant, because the right amount depends on the organisation. The aim is to get a human to a well-evidenced decision within the hours an attacker spends looking around, not to remove the human.

Fifteen hours is plenty of time, if the investigation starts in the first one.

If you want to see how that works against your own Microsoft estate, book a demo.

Agentic AIStorm-3168AzureService PrincipalsNon-Human IdentitiesCloud SecurityAI SOCMicrosoft SentinelSecurity OperationsKQL

Ready to see the agents work?

Book a demo of CYBERSHIELD AI against a real scenario.