Back to Intelligence

AI-Cheap Retry Loops: Detecting Iterative Cloud Privilege Escalation Before It Succeeds

SA
Security Arsenal Team
September 25, 2026
12 min read

Security leaders keep debating whether AI will produce an entirely new class of cyberattack. The nearer change is quieter — and it is already inside your telemetry. AI has made a failed attack cheap to retry.

The routine version looks like this: an attacker lands on a low-privilege cloud account — via phished credentials, a leaked access key, or a token scraped from a CI runner — and the first attempt at unauthorized privilege gain goes nowhere. That dead end used to cost hours of documentation reading, trial-and-error against IAM policy semantics, and careful movement to avoid tripping detection. Now an AI-assisted operator (or an automated agent) can enumerate the account's effective permissions, generate candidate escalation paths, and retry dozens of variations in minutes. The cost of failure has collapsed to near zero.

For defenders, this changes the math on alert triage. A single failed iam:AttachUserPolicy or a denied Microsoft.Authorization/roleAssignments/write call has historically been a low-severity, close-and-move-on event. In 2026, that single failure is frequently attempt #1 of 40. The SOC doesn't need to start over with every alert — it needs to correlate retries across time, identity, and cloud control-plane actions, and treat iterative failure as a high-fidelity attack signal. This post gives you the detection engineering, hunting queries, and hardening steps to do exactly that.

Technical Analysis

The attack pattern

This is not a vulnerability in the classic sense — there is no CVE, no patch, no vendor advisory. It is an exploitation of economics: the defender's per-alert cost is fixed, while the attacker's per-attempt cost has dropped to effectively nothing.

The observed attack chain typically follows this sequence:

  1. Initial access on a low-privilege identity — compromised IAM user, service account, managed identity, or federated SSO session. MITRE ATT&CK T1078.004 — Valid Accounts: Cloud Accounts.
  2. Permission discovery — automated enumeration of attached policies, group memberships, role trust relationships, and (in AWS) simulated principal policies via iam:SimulatePrincipalPolicy or iam:GetAccountAuthorizationDetails. AI tooling accelerates the reading of IAM policy documents that previously required specialist knowledge.
  3. Iterative privilege escalation attempts — rapid, varied attempts against the known cloud privesc paths:
    • AWS: iam:AttachUserPolicy, iam:AttachRolePolicy, iam:PutUserPolicy, iam:CreatePolicyVersion, iam:CreateAccessKey (on another user), iam:CreateLoginProfile, lambda:CreateFunction + iam:PassRole, lambda:UpdateFunctionCode, ec2:RunInstances + iam:PassRole, glue:CreateDevEndpoint, cloudformation:CreateStack, datapipeline:CreatePipeline.
    • Azure: Microsoft.Authorization/roleAssignments/write, Microsoft.ManagedIdentity/userAssignedIdentities/assign/action, Automation Account runbook creation, Microsoft.Compute/virtualMachines/runCommand/action.
    • GCP: iam.serviceAccounts.actAs, iam.serviceAccountKeys.create, deploymentmanager.deployments.create.
  4. Success, then rapid consolidation — once one path works, the attacker immediately creates persistence (new access keys, login profiles, role trust modifications) — ATT&CK T1098 — Account Manipulation.

What changed

The pre-AI version of this chain had a natural rate limiter: human cognition. Each failed attempt forced the attacker to stop, read, reason, and reformulate. Failed attempts were sparse in time. AI assistance removes that limiter — failed attempts now arrive in dense clusters, often against the same identity from the same source, spanning multiple escalation techniques in a single session.

That density is a gift to defenders — if the SOC is looking for it. The tragedy is that most SIEM content still fires one alert per failed API call, each one triaged in isolation, each one closed as "insufficient permissions, no impact." The attacker is doing statistics on your blind spots while your analysts close tickets.

Exploitation status

This pattern is actively observed in the wild as an operational characteristic of cloud intrusions in 2025–2026, not a theoretical construct. It requires no zero-day, no malware, and no exploit code — only valid low-privilege credentials and control-plane API access, which is why it evades EDR-centric detection stacks almost entirely.

Detection & Response

The defensive core insight: correlate failures, don't clear them. A single denied IAM call is noise. Five distinct privilege-escalation API calls denied for the same identity within ten minutes is an intrusion in progress.

Sigma Rules

The first rule targets the AWS control plane (ingest CloudTrail into your SIEM). The second targets Azure Activity. Both key on failed calls — the retry signature — because successful privesc should already be covered by separate, higher-severity content.

YAML
---
title: AWS CloudTrail Failed IAM Privilege Escalation Attempt
id: 3f8a2b71-9c4d-4e6f-a1b2-8d7e5f6c9a01
status: experimental
description: Detects denied AWS API calls associated with known privilege escalation paths. A single event is medium severity; SOC should correlate multiple events per identity into a single high-severity incident rather than triaging each independently.
references:
  - https://attack.mitre.org/techniques/T1098/
  - https://attack.mitre.org/techniques/T1078/004/
  - https://thehackernews.com/2026/09/the-soc-doesnt-need-to-start-over-with.html
author: Security Arsenal
date: 2026/09/15
tags:
  - attack.privilege_escalation
  - attack.persistence
  - attack.t1098
logsource:
  product: aws
  service: cloudtrail
detection:
  selection_api:
    eventSource:
      - 'iam.amazonaws.com'
      - 'lambda.amazonaws.com'
      - 'ec2.amazonaws.com'
      - 'cloudformation.amazonaws.com'
    eventName:
      - 'AttachUserPolicy'
      - 'AttachRolePolicy'
      - 'PutUserPolicy'
      - 'PutRolePolicy'
      - 'CreatePolicyVersion'
      - 'CreateAccessKey'
      - 'CreateLoginProfile'
      - 'UpdateLoginProfile'
      - 'CreateFunction*'
      - 'UpdateFunctionCode'
      - 'RunInstances'
      - 'CreateStack'
      - 'PassRole'
  selection_denied:
    errorCode:
      - 'AccessDenied'
      - 'Client.UnauthorizedOperation'
      - 'UnauthorizedOperation'
  condition: selection_api and selection_denied
falsepositives:
  - Developers legitimately testing IAM permissions in sandbox accounts
  - Misconfigured IaC pipelines (Terraform apply with insufficient role)
level: medium
---
title: Azure Failed Role Assignment or Elevation Attempt
id: 6c1d9e42-7a3b-4f58-b2c9-1e4a6d8f0b23
status: experimental
description: Detects failed Azure control-plane operations consistent with privilege escalation retry loops, including denied role assignment writes and managed identity assignment attempts. Correlate per-caller over short windows.
references:
  - https://attack.mitre.org/techniques/T1098/
  - https://thehackernews.com/2026/09/the-soc-doesnt-need-to-start-over-with.html
author: Security Arsenal
date: 2026/09/15
tags:
  - attack.privilege_escalation
  - attack.t1098
  - attack.t1078.004
logsource:
  product: azure
  service: activitylogs
detection:
  selection_op:
    operationName:
      - 'MICROSOFT.AUTHORIZATION/ROLEASSIGNMENTS/WRITE'
      - 'MICROSOFT.MANAGEDIDENTITY/USERASSIGNEDIDENTITIES/ASSIGN/ACTION'
      - 'MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE'
      - 'MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION'
  selection_fail:
    properties.statusCode:
      - 'Forbidden'
      - 'AuthorizationFailed'
      - 'Unauthorized'
  condition: selection_op and selection_fail
falsepositives:
  - Administrators hitting RBAC scope boundaries during legitimate change windows
level: medium

Tuning note from the field: deploy these at medium, then build a SIEM-level correlation rule (or Sentinel analytics rule) that promotes the event to high/critical when the same identity produces 3 or more distinct matching events within 15 minutes. That aggregation layer is where the actual detection value lives — it converts retry noise into a single actionable incident.

KQL — Microsoft Sentinel Hunt Query

This query hunts the retry pattern directly in AWS CloudTrail data ingested into Sentinel. It bins failed privilege-escalation API calls per identity into 10-minute windows and surfaces identities attempting multiple distinct escalation techniques — the signature of an AI-assisted operator cycling through the privesc playbook.

KQL — Microsoft Sentinel / Defender
// Hunt: Iterative cloud privilege escalation retry loops (AWS CloudTrail)
// Surfaces identities making 3+ distinct failed privesc API calls within 10 minutes
let PrivescEvents = dynamic([
  "AttachUserPolicy","AttachRolePolicy","PutUserPolicy","PutRolePolicy",
  "CreatePolicyVersion","CreateAccessKey","CreateLoginProfile","UpdateLoginProfile",
  "CreateFunction20150331","UpdateFunctionCode20150331v2","RunInstances",
  "CreateStack","PassRole","SimulatePrincipalPolicy","GetAccountAuthorizationDetails"
]);
AWSCloudTrail
| where TimeGenerated > ago(24h)
| where EventName in~ (PrivescEvents)
| extend Failed = (ErrorCode in~ ("AccessDenied","Client.UnauthorizedOperation","UnauthorizedOperation"))
| extend Identity = tostring(UserIdentityArn)
| summarize
    AttemptCount = count(),
    FailedCount = countif(Failed),
    DistinctTechniques = dcount(EventName),
    Techniques = make_set(EventName),
    SourceIPs = make_set(SourceIpAddress),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
  by Identity, bin(TimeGenerated, 10m)
| where FailedCount >= 3 and DistinctTechniques >= 2
| project Identity, TimeGenerated, AttemptCount, FailedCount, DistinctTechniques, Techniques, SourceIPs, FirstSeen, LastSeen
| order by FailedCount desc;

For Azure environments, the equivalent hunts AzureActivity for denied role-assignment writes per caller:

KQL — Microsoft Sentinel / Defender
// Hunt: Azure RBAC escalation retry pattern
AzureActivity
| where TimeGenerated > ago(24h)
| where OperationNameValue in~ (
    "MICROSOFT.AUTHORIZATION/ROLEASSIGNMENTS/WRITE",
    "MICROSOFT.MANAGEDIDENTITY/USERASSIGNEDIDENTITIES/ASSIGN/ACTION",
    "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE",
    "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION")
| extend Failed = (ActivityStatusValue in~ ("Failed","Unauthorized") or Properties.statusCode in~ ("Forbidden","AuthorizationFailed"))
| summarize
    AttemptCount = count(),
    FailedCount = countif(Failed),
    DistinctOps = dcount(OperationNameValue),
    Ops = make_set(OperationNameValue)
  by Caller, CallerIpAddress, bin(TimeGenerated, 10m)
| where FailedCount >= 2
| order by FailedCount desc;

Velociraptor VQL — Endpoint Hunt

Cloud control-plane abuse usually leaves an endpoint footprint: the attacker drives aws, az, or gcloud CLI from a compromised workstation or jump host, often from an unusual parent process (an interpreter, an automation agent, or a shell spawned by an office document). This artifact hunts for cloud CLI invocations with privilege-relevant subcommands spawned from suspicious parents — catching the retry loop at the source host before it ever reaches the cloud.

VQL — Velociraptor
-- Hunt: Cloud CLI privilege escalation attempts from suspicious parent processes
-- Deploy across fleet; enrich results with parent lineage to spot scripted retry loops
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime,
       getppid(pid=Pid) as ParentPid
FROM pslist()
WHERE (
    Name =~ '(?i)^(aws|az|gcloud|gsutil)(\.exe)?$'
    AND CommandLine =~ '(?i)(iam|policy|role-assignment|attach|pass-role|create-access-key|create-login-profile|service-accounts|act-as)'
  )
  OR (
    -- Cloud CLIs spawned by script interpreters or unusual parents
    CommandLine =~ '(?i)(aws|az |gcloud).*(attach|policy|access-key|role)'
    AND Name =~ '(?i)(python|powershell|pwsh|cmd|wscript|cscript|bash|sh)(\.exe)?$'
  )

Follow up on hits by pulling the host's shell history (glob() against ~/.aws/**, %USERPROFILE%\.aws\*, and PowerShell/bash history files) to reconstruct the full sequence of attempted escalation commands — the retry loop will be written out in plain text.

Remediation / Hardening Script

There is no patch for "attacks are cheaper now." The remediation is architectural: shrink the number of identities that can attempt privilege escalation, and make sure the attempts are logged. This Bash audit script checks an AWS account for the most common enablers of retry-loop success — over-permissive wildcard IAM policies, stale access keys, and CloudTrail coverage gaps.

Bash / Shell
#!/usr/bin/env bash
# Security Arsenal — AWS IAM Privilege Escalation Surface Audit
# Run with a read-only auditor role. Review all findings before action.
set -euo pipefail

echo "=== [1/4] Users/roles with wildcard or iam:* permissions (privesc surface) ==="
aws iam list-policies --scope Local --only-attached \
  --query 'Policies[*].{Arn:Arn,Name:PolicyName}' --output json | \
while read -r arn; do
  aws iam get-policy-version \
    --policy-arn "$(echo "$arn" | jq -r '.Arn')" \
    --version-id "$(aws iam get-policy --policy-arn "$(echo "$arn" | jq -r '.Arn')" \
      --query 'Policy.DefaultVersionId' --output text)" \
    --query 'PolicyVersion.Document.Statement[?Effect==`Allow`]' --output json 2>/dev/null
 done | jq -r '.[] | select((.Action|tostring|test("iam:\\*|\\*")) and (.Resource=="*"))' | sort -u

echo "=== [2/4] Access keys older than 90 days (stale credential risk) ==="
cutoff=$(date -u -d "90 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-90d +%Y-%m-%dT%H:%M:%SZ)
aws iam list-users --query 'Users[*].UserName' --output text | tr '\t' '\n' | \
while read -r user; do
  aws iam list-access-keys --user-name "$user" \
    --query "AccessKeyMetadata[?CreateDate<='$cutoff'].{User:UserName,Key:AccessKeyId,Created:CreateDate,Status:Status}" \
    --output table
done

echo "=== [3/4] CloudTrail multi-region coverage and management event logging ==="
aws cloudtrail describe-trails --include-shadow-trails \
  --query 'trailList[*].{Name:Name,MultiRegion:IsMultiRegionTrail,LogValidation:LogFileValidationEnabled}' \
  --output table
echo "[!] Verify at least one multi-region trail with management events AND log file validation enabled."

echo "=== [4/4] Roles assumable by external accounts (trust policy exposure) ==="
aws iam list-roles --query 'Roles[*].{Role:RoleName,Arn:Arn}' --output json | \
jq -r '.[].Arn' | while read -r role; do
  aws iam get-role --role-name "$(basename "$role")" \
    --query 'Role.AssumeRolePolicyDocument.Statement[?Effect==`Allow`].Principal' \
    --output json 2>/dev/null | jq -r '.[] | select(.AWS != null) | .AWS' | \
    grep -v ":$(aws sts get-caller-identity --query Account --output text):" || true
done

echo ""
echo "Audit complete. Findings to remediate:"
echo " - Replace wildcard iam:* policies with least-privilege scoped policies"
echo " - Rotate/disable stale access keys; migrate workloads to IAM roles/SSO"
echo " - Ensure CloudTrail management events feed your SIEM (retry detection depends on it)"
echo " - Apply a deny-SCP on iam:AttachUserPolicy/CreateAccessKey outside break-glass roles"

Remediation

Because this is a technique shift rather than a patchable flaw, remediation is layered. Prioritize in this order:

1. Fix the SOC workflow (this week).

  • Stop triaging cloud control-plane denials as isolated tickets. Build correlation that aggregates failed privesc API calls per identity per window (the KQL above is a starting point) and promotes clustered retries to a single high-severity incident.
  • Add "number of distinct escalation techniques attempted" as a severity modifier. One technique failing twice is curiosity; five techniques failing in ten minutes is an operator.
  • Preserve failed-attempt context in the incident record. When attempt #23 succeeds, your IR team needs attempts #1–22 in the same case file to scope the intrusion and understand the attacker's path.

2. Shrink the privilege escalation surface (30 days).

  • Eliminate wildcard IAM actions (iam:*, *:*) from human and workload identities. Replace with scoped, resource-constrained policies.
  • In AWS, deploy a Service Control Policy denying iam:AttachUserPolicy, iam:CreateAccessKey, iam:CreateLoginProfile, and iam:CreatePolicyVersion except to explicitly named break-glass roles. The attacker can retry forever — the SCP ensures every retry fails at the organization level, below the identity's own policy evaluation.
  • In Azure, enforce PIM-eligible (not standing) privileged role assignments and alert on any direct roleAssignments/write outside PIM flows.
  • Remove iam:PassRole from identities that don't need it, and where it is required, constrain iam:PassedToService.

3. Make the telemetry non-optional (30 days).

  • AWS: multi-region CloudTrail with management events, log file validation, and organization-level trail (so a compromised account cannot disable its own logging). Send to a SIEM the attacker cannot reach.
  • Azure: Activity Log to a Log Analytics workspace with a locked retention policy; enable Microsoft Defender for Cloud control-plane alerts.
  • Verify ingestion weekly. A retry-loop detection rule against an empty table is exactly as useful as no rule at all.

4. Reduce credential replay value (90 days).

  • Enforce short-lived credentials: SSO/Identity Center for humans, instance profiles/managed identities for workloads. Kill long-lived IAM user access keys wherever they survive (the audit script above finds them).
  • Apply session policies and IP/condition constraints (aws:SourceIp, aws:ViaAWSService) to sensitive roles so a stolen low-privilege key is useless off-network.

5. Exercise the pattern (quarterly).

  • Run a purple-team replay of the retry loop: grant a test identity a low-privilege policy, attempt the known escalation paths, and confirm your correlation layer fires one incident — not forty alerts, and not zero. If your analysts would have closed 40 tickets, the exercise just paid for itself.

The strategic takeaway for CISOs: AI did not hand attackers a new exploit. It handed them free retries, which means the marginal cost of probing your IAM misconfigurations is now zero. Every over-permissive policy you tolerate will eventually be found — not by a patient expert, but by a tireless script. Least privilege is no longer a hygiene aspiration; it is the only control that makes infinite retries converge on failure.

Related Resources

Security Arsenal Managed SOC Services AlertMonitor Platform Book a SOC Assessment soc-mdr Intel Hub

Is your security operations ready?

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