{
  "hunt": {
    "meta": {
      "tlp": "clear",
      "hunt": {
        "handoff": "promote-to-detection",
        "trigger": "intel-report",
        "methodology": "model-assisted",
        "applicability": "campaign-specific",
        "justification": "The shift toward agentic cloud attacks allows adversaries to destroy infrastructure in minutes; identifying the reconnaissance phase provides the only window to prevent catastrophic resource loss."
      },
      "name": "Storm-3168: Automated Azure Resource Destruction and Recovery Inhibition",
      "type": "investigation",
      "labels": [
        "hunt",
        "attack.t1087.004",
        "attack.t1046",
        "attack.t1580",
        "attack.t1485",
        "attack.t1486",
        "attack.t1490",
        "attack.t1528"
      ],
      "series": {
        "slug": "storm-3168-agentic-driven-cloud-attacks-using-compromised-service-principals",
        "index": 1,
        "title": "Storm-3168: Agentic-driven cloud attacks using compromised service principals",
        "total": 2
      },
      "related": [
        {
          "hunt": "exposed-secrets-github-history",
          "reason": "Initial access via secrets in GitHub history requires a repository-focused hunt.",
          "relation": "out-of-scope-alternative"
        }
      ],
      "targets": {
        "hunter": {
          "name": "Hunt agent",
          "agent": true
        },
        "analyst": {
          "name": "Tier-2 analyst",
          "role": "analyst"
        },
        "endpoint": {
          "name": "Endpoint telemetry (hb_ surfaces)",
          "category": "endpoint",
          "telemetry": [
            "endpoint"
          ]
        },
        "identity": {
          "name": "Identity / sign-in telemetry",
          "category": "identity",
          "telemetry": [
            "identity"
          ]
        }
      },
      "analysis": "A single resource deletion rule is noisy. This hunt correlates a specific Python user-agent with a rapid discovery phase and a subsequent multi-service destruction sequence, capturing the behavior of automated cloud scripts.",
      "coverage": [
        {
          "stage": "reconnaissance-cloud-discovery",
          "steps": [
            "identify-suspicious-principals",
            "recon-volume",
            "ua-prevalence"
          ],
          "status": "covered"
        },
        {
          "stage": "impact-resource-deletion",
          "steps": [
            "automated-destruction"
          ],
          "status": "covered"
        },
        {
          "stage": "inhibit-recovery-lock-removal",
          "steps": [
            "automated-destruction"
          ],
          "status": "covered"
        },
        {
          "stage": "credential-access-storage-keys",
          "steps": [
            "automated-destruction"
          ],
          "status": "covered"
        },
        {
          "stage": "initial-access-exposed-secret",
          "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "reconnaissance-application-probing",
          "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
          "status": "out_of_scope"
        }
      ],
      "scenario": {
        "stages": [
          {
            "name": "Service principal credential leak",
            "slug": "initial-access-exposed-secret",
            "tactic": "initial-access",
            "techniques": [
              "T1552.001"
            ],
            "observables": [
              "plaintext client_id, client_secret, and tenant_id in public GitHub issue history"
            ]
          },
          {
            "name": "Rapid Azure resource enumeration",
            "slug": "reconnaissance-cloud-discovery",
            "tactic": "discovery",
            "techniques": [
              "T1087.004",
              "T1046",
              "T1580"
            ],
            "observables": [
              "python-requests/2.34.2",
              "300+ successful read operations",
              "enumeration of Azure VMs, subscriptions, and resource groups",
              "enumeration of App Service configuration stores",
              "probing for Azure OpenSearch resources"
            ]
          },
          {
            "name": "Automated resource destruction",
            "slug": "impact-resource-deletion",
            "tactic": "impact",
            "techniques": [
              "T1485",
              "T1486"
            ],
            "observables": [
              "100+ storage account deletion attempts",
              "deletion of Azure Key Vault",
              "deletion of Azure Function App",
              "deletion of Azure App service plan",
              "failed SQL database deletions due to unsupported API version"
            ]
          },
          {
            "name": "Removal of recovery protections",
            "slug": "inhibit-recovery-lock-removal",
            "tactic": "impact",
            "techniques": [
              "T1490"
            ],
            "observables": [
              "attempts to delete Azure Site Recovery locks",
              "attempts to delete Azure Backup protection locks"
            ]
          },
          {
            "name": "Storage account key collection",
            "slug": "credential-access-storage-keys",
            "tactic": "credential-access",
            "techniques": [
              "T1528"
            ],
            "observables": [
              "ListKeys requests against Azure Storage Accounts",
              "30+ successful key retrieval operations"
            ]
          },
          {
            "name": "Web application vulnerability probing",
            "slug": "reconnaissance-application-probing",
            "tactic": "discovery",
            "techniques": [
              "T1595.002"
            ],
            "observables": [
              "GET /api/v1/validate/code",
              "WordPress administration path probing",
              "PHP-CGI path probing"
            ]
          }
        ],
        "summary": "Storm-3168 (JADEPUFFER) leverages Azure service principal credentials exposed in public GitHub issue histories to perform automated cloud resource destruction. The actor executes rapid reconnaissance before bulk-deleting storage accounts, key vaults, and databases while attempting to remove backup and recovery locks to inhibit restoration."
      },
      "severity": "high",
      "rationale": "Focus on service principals using Python-based request libraries. The hunt starts with Azure authentication logs and pivots to API activity to identify the breadth of the impact.",
      "guardrails": {
        "claims": "no_unsupported",
        "evidence": "citation_required",
        "telemetry": "untrusted",
        "missing_data": "not_benign"
      },
      "hypothesis": "A compromised service principal is executing an automated sequence of Azure resource discovery, mass deletion, and credential collection to facilitate a cloud-native ransomware operation.",
      "parameters": {
        "scope_hosts": {
          "type": "list[host]",
          "default": [],
          "description": "List of suspicious Service Principal names identified in the scoping phase."
        },
        "campaign_uas": {
          "from": {
            "ref": "https://www.microsoft.com/en-us/security/blog/2026/09/25/storm-3168-agentic-driven-cloud-attacks-using-compromised-service-principals/",
            "kind": "article",
            "observed": "2026-09-25"
          },
          "type": "list[string]",
          "default": [
            "python-requests/2.34.2"
          ],
          "description": "User agents observed in Storm-3168 activity."
        },
        "lookback_days": {
          "type": "number",
          "default": "14",
          "description": "Days of cloud API activity to examine."
        }
      },
      "provenance": {
        "authors": [
          {
            "org": "huntbase.io",
            "name": "Huntbase hunt generation"
          }
        ],
        "generated": {
          "by": "huntbase-hunt-generation",
          "from": "https://www.microsoft.com/en-us/security/blog/2026/09/25/storm-3168-agentic-driven-cloud-attacks-using-compromised-service-principals/",
          "gates": [
            "dry-run",
            "lint",
            "critic"
          ],
          "model": "hb_google/gemini-3-flash-preview"
        }
      },
      "references": [
        {
          "url": "https://www.microsoft.com/en-us/security/blog/2026/09/25/storm-3168-agentic-driven-cloud-attacks-using-compromised-service-principals/",
          "name": "Storm-3168: Agentic-driven cloud attacks using compromised service principals"
        }
      ],
      "blind_spots": [
        {
          "id": "lack-of-api-version-detail",
          "risk": "If the logs do not record the API version used, the analyst might mistake a failed deletion attempt for a simple configuration error.",
          "stage": "impact-resource-deletion",
          "question": "What specifically caused the SQL deletion failures?",
          "requires": "Cloud audit logs with full request metadata"
        },
        {
          "id": "secret-rotation-visibility",
          "risk": "We can see the retrieval but not if the actor successfully applied the keys to access data without high-fidelity storage logs.",
          "stage": "credential-access-storage-keys",
          "question": "Were the retrieved storage keys rotated by the actor?",
          "requires": "hb_account_change for cloud secrets"
        }
      ]
    },
    "name": "Storm-3168: Automated Azure Resource Destruction and Recovery Inhibition",
    "description": "This hunt targets the activity of Storm-3168 (JADEPUFFER), an actor using agentic automation to conduct rapid cloud attacks. We analyze Azure control-plane logs for an initial phase of broad resource reconnaissance, followed by a dense sequence of storage, database, and identity resource deletions. The hunt also searches for attempts to remove recovery protection locks and retrieve storage account access keys, identifying the hallmarks of a cloud-native ransomware operation."
  },
  "nodes": [
    {
      "id": "hypothesis",
      "type": "hypothesis",
      "label": "Hypothesis",
      "config": {
        "tags": [],
        "series": {
          "slug": "storm-3168-agentic-driven-cloud-attacks-using-compromised-service-principals",
          "index": 1,
          "title": "Storm-3168: Agentic-driven cloud attacks using compromised service principals",
          "total": 2
        },
        "coverage": [
          {
            "stage": "reconnaissance-cloud-discovery",
            "steps": [
              "identify-suspicious-principals",
              "recon-volume",
              "ua-prevalence"
            ],
            "status": "covered"
          },
          {
            "stage": "impact-resource-deletion",
            "steps": [
              "automated-destruction"
            ],
            "status": "covered"
          },
          {
            "stage": "inhibit-recovery-lock-removal",
            "steps": [
              "automated-destruction"
            ],
            "status": "covered"
          },
          {
            "stage": "credential-access-storage-keys",
            "steps": [
              "automated-destruction"
            ],
            "status": "covered"
          },
          {
            "stage": "initial-access-exposed-secret",
            "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "reconnaissance-application-probing",
            "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
            "status": "out_of_scope"
          }
        ],
        "rationale": "A compromised service principal is executing an automated sequence of Azure resource discovery, mass deletion, and credential collection to facilitate a cloud-native ransomware operation.",
        "blind_spots": [
          {
            "id": "lack-of-api-version-detail",
            "risk": "If the logs do not record the API version used, the analyst might mistake a failed deletion attempt for a simple configuration error.",
            "stage": "impact-resource-deletion",
            "question": "What specifically caused the SQL deletion failures?",
            "requires": "Cloud audit logs with full request metadata"
          },
          {
            "id": "secret-rotation-visibility",
            "risk": "We can see the retrieval but not if the actor successfully applied the keys to access data without high-fidelity storage logs.",
            "stage": "credential-access-storage-keys",
            "question": "Were the retrieved storage keys rotated by the actor?",
            "requires": "hb_account_change for cloud secrets"
          }
        ],
        "scoping_notes": "Focus on service principals using Python-based request libraries. The hunt starts with Azure authentication logs and pivots to API activity to identify the breadth of the impact.",
        "beyond_detection": "A single resource deletion rule is noisy. This hunt correlates a specific Python user-agent with a rapid discovery phase and a subsequent multi-service destruction sequence, capturing the behavior of automated cloud scripts."
      }
    },
    {
      "id": "identify-suspicious-principals",
      "type": "query",
      "label": "Identify suspicious service principal sign-ins",
      "config": {
        "dsl": "sqlite",
        "role": "scoping",
        "source": "identity",
        "content": "SELECT actor_user_name, src_endpoint_ip, user_agent, COUNT(*) as login_count, MIN(time) as first_seen FROM hb_auth_signin WHERE provider = 'azure' AND instr(',' || '{{campaign_uas}}' || ',', ',' || user_agent || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY actor_user_name, src_endpoint_ip, user_agent",
        "surface": "hb_auth_signin",
        "description": "Scope the hunt to Azure service principals using the campaign's specific Python user agent.",
        "expected_signal": "A list of service principal names that have authenticated using the suspicious Python library. Silence suggests the actor's toolkit is not present."
      },
      "parents": [
        {
          "id": "hypothesis"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "scoping",
        "label": "Identify suspicious service principal sign-ins",
        "reads": [
          "actor_user_name",
          "src_endpoint_ip",
          "user_agent",
          "time",
          "provider"
        ],
        "source": "hb_auth_signin",
        "target": "identity",
        "content": "SELECT actor_user_name, src_endpoint_ip, user_agent, COUNT(*) as login_count, MIN(time) as first_seen FROM hb_auth_signin WHERE provider = 'azure' AND instr(',' || '{{campaign_uas}}' || ',', ',' || user_agent || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY actor_user_name, src_endpoint_ip, user_agent",
        "silence": "not_evidence_of_absence",
        "expected": "A list of service principal names that have authenticated using the suspicious Python library. Silence suggests the actor's toolkit is not present.",
        "verified": "dry-run",
        "verified_at": "2026-09-26"
      }
    },
    {
      "id": "recon-volume",
      "type": "query",
      "label": "Analyze discovery operation volume",
      "config": {
        "dsl": "sqlite",
        "role": "baseline",
        "source": "endpoint",
        "content": "SELECT actor_user_name, api_operation, api_service_name, COUNT(*) as op_count FROM hb_cloud_api_activity WHERE activity_id = 2 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY actor_user_name, api_operation, api_service_name HAVING op_count > 50 ORDER BY op_count DESC",
        "surface": "hb_cloud_api_activity",
        "description": "Find service principals performing a high volume of read operations, typical of automated discovery.",
        "expected_signal": "Service principals with hundreds of successful read/list operations across multiple subscriptions or resource groups."
      },
      "parents": [
        {
          "id": "identify-suspicious-principals"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "baseline",
        "label": "Analyze discovery operation volume",
        "reads": [
          "actor_user_name",
          "api_operation",
          "api_service_name",
          "activity_id",
          "time"
        ],
        "source": "hb_cloud_api_activity",
        "target": "endpoint",
        "content": "SELECT actor_user_name, api_operation, api_service_name, COUNT(*) as op_count FROM hb_cloud_api_activity WHERE activity_id = 2 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY actor_user_name, api_operation, api_service_name HAVING op_count > 50 ORDER BY op_count DESC",
        "silence": "not_evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "first_seen"
        },
        "expected": "Service principals with hundreds of successful read/list operations across multiple subscriptions or resource groups.",
        "verified": "dry-run",
        "prevalence": {
          "by": "actor_user_name",
          "key": [
            "api_operation"
          ],
          "rare_below": 3
        },
        "verified_at": "2026-09-26"
      }
    },
    {
      "id": "ua-prevalence",
      "type": "query",
      "label": "Analyze user agent prevalence",
      "config": {
        "dsl": "sqlite",
        "role": "baseline",
        "source": "endpoint",
        "content": "SELECT user_agent, COUNT(DISTINCT actor_user_name) as principal_count, COUNT(*) as call_count FROM hb_cloud_api_activity WHERE time >= datetime('now', '-{{lookback_days}} days') GROUP BY user_agent ORDER BY principal_count ASC",
        "surface": "hb_cloud_api_activity",
        "description": "Stack-count user agents associated with Azure API activity to see if the campaign UA is an outlier.",
        "expected_signal": "The Campaign user agent (python-requests/2.34.2) appearing for very few service principals, confirming its rarity."
      },
      "parents": [
        {
          "id": "identify-suspicious-principals"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "baseline",
        "label": "Analyze user agent prevalence",
        "reads": [
          "user_agent",
          "actor_user_name",
          "time"
        ],
        "source": "hb_cloud_api_activity",
        "target": "endpoint",
        "content": "SELECT user_agent, COUNT(DISTINCT actor_user_name) as principal_count, COUNT(*) as call_count FROM hb_cloud_api_activity WHERE time >= datetime('now', '-{{lookback_days}} days') GROUP BY user_agent ORDER BY principal_count ASC",
        "silence": "not_evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "first_seen"
        },
        "expected": "The Campaign user agent (python-requests/2.34.2) appearing for very few service principals, confirming its rarity.",
        "verified": "dry-run",
        "prevalence": {
          "by": "actor_user_name",
          "key": [
            "user_agent"
          ],
          "rare_below": 5
        },
        "verified_at": "2026-09-26"
      }
    },
    {
      "id": "triage-reconnaissance",
      "type": "analytic",
      "label": "Assess reconnaissance evidence",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint",
          "identity"
        ],
        "context": [
          "identify-suspicious-principals",
          "recon-volume",
          "ua-prevalence"
        ],
        "objective": "Determine if any service principal exhibits signs of automated reconnaissance against Azure resources, specifically focusing on those using the campaign user agent.",
        "description": "An agent evaluates whether the identified principals exhibit automated reconnaissance patterns linked to the Storm-3168 campaign.",
        "max_iterations": 3,
        "expected_signal": "A verdict per principal citing discovery breadth and UA rarity.",
        "success_criteria": "A per-principal classification of malicious, suspicious, or benign based on reconnaissance patterns."
      },
      "parents": [
        {
          "id": "recon-volume",
          "kind": "merge"
        },
        {
          "id": "ua-prevalence",
          "kind": "merge"
        }
      ]
    },
    {
      "id": "automated-destruction",
      "type": "query",
      "label": "Detect automated destruction and key retrieval",
      "config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "source": "endpoint",
        "content": "SELECT time, actor_user_name, api_operation, resource_name, status, error_code FROM hb_cloud_api_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || actor_user_name || ',') > 0) AND (activity_id = 4 OR LOWER(api_operation) LIKE '%delete%' OR LOWER(api_operation) LIKE '%listkeys%') AND time >= datetime('now', '-{{lookback_days}} days') ORDER BY time DESC",
        "surface": "hb_cloud_api_activity",
        "description": "Search for mass resource deletion and credential collection following the reconnaissance phase.",
        "expected_signal": "A dense sequence of deletion operations for storage accounts and key vaults. Failed SQL deletions with API errors and multiple ListKeys operations confirm the ransomware objective."
      },
      "parents": [
        {
          "id": "triage-reconnaissance"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "label": "Detect automated destruction and key retrieval",
        "reads": [
          "actor_user_name",
          "api_operation",
          "resource_name",
          "status",
          "error_code",
          "activity_id",
          "time"
        ],
        "source": "hb_cloud_api_activity",
        "target": "endpoint",
        "content": "SELECT time, actor_user_name, api_operation, resource_name, status, error_code FROM hb_cloud_api_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || actor_user_name || ',') > 0) AND (activity_id = 4 OR LOWER(api_operation) LIKE '%delete%' OR LOWER(api_operation) LIKE '%listkeys%') AND time >= datetime('now', '-{{lookback_days}} days') ORDER BY time DESC",
        "silence": "not_evidence_of_absence",
        "expected": "A dense sequence of deletion operations for storage accounts and key vaults. Failed SQL deletions with API errors and multiple ListKeys operations confirm the ransomware objective.",
        "verified": "dry-run",
        "verified_at": "2026-09-26"
      }
    },
    {
      "id": "triage-final-verdict",
      "type": "analytic",
      "label": "Analyze destruction and recovery inhibition",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint",
          "identity"
        ],
        "context": [
          "triage-reconnaissance",
          "automated-destruction"
        ],
        "objective": "Evaluate the combined evidence of discovery, mass resource deletion, failed SQL deletions, and storage key collection to confirm a ransomware-aligned campaign.",
        "description": "An agent synthesizes the entire attack chain to determine if the environment has suffered an automated destruction event.",
        "max_iterations": 4,
        "expected_signal": "A final verdict linking reconnaissance principals to destructive actions and intent.",
        "success_criteria": "A comprehensive report naming the malicious service principals and the resources affected."
      },
      "parents": [
        {
          "id": "automated-destruction"
        }
      ]
    },
    {
      "id": "route-on-verdict",
      "type": "checkpoint",
      "label": "Route on malicious activity",
      "config": {
        "fuzzy": true,
        "judge": "hunter",
        "question": "the agent verdict for triage-final-verdict is malicious and confirms automated resource deletion",
        "condition": "the agent verdict for triage-final-verdict is malicious and confirms automated resource deletion",
        "blind_spot": "lack-of-api-version-detail",
        "confidence": "high",
        "description": "Direct the workflow based on the agent's final assessment of automated destruction.",
        "checkpoint_type": "mandatory"
      },
      "parents": [
        {
          "id": "triage-final-verdict"
        }
      ]
    },
    {
      "id": "revoke-compromised-sp",
      "type": "action",
      "label": "Revoke compromised service principal",
      "config": {
        "target": "identity",
        "description": "Immediately disable the compromised identity to prevent further resource destruction.",
        "instructions": "Disable the service principal(s) identified as malicious and revoke all active OAuth tokens to halt the destructive campaign.",
        "action_approval": "required"
      },
      "parents": [
        {
          "id": "route-on-verdict",
          "branch": "on_supports"
        }
      ]
    },
    {
      "id": "impact-assessment",
      "type": "task",
      "label": "Assess destruction and initiate recovery",
      "config": {
        "assignee": "analyst",
        "description": "An analyst reviews the extent of the damage and begins restoring resources from backup.",
        "instructions": "Verify the list of deleted storage accounts, SQL databases, and key vaults. Identify resources where deletion was blocked by locks or protection. Initiate restoration from Azure Backup or Site Recovery."
      },
      "parents": [
        {
          "id": "route-on-verdict",
          "branch": "default"
        },
        {
          "id": "route-on-verdict",
          "branch": "on_unavailable"
        },
        {
          "id": "revoke-compromised-sp"
        }
      ]
    },
    {
      "id": "close-out",
      "type": "task",
      "label": "Close hunt and update detections",
      "config": {
        "assignee": "analyst",
        "description": "Final close-out of the hunt and transition to detection engineering.",
        "instructions": "Document the hunt findings. If a confirmed intrusion occurred, escalate to IR. If not, record any benign Python-based automation for exclusion tuning."
      },
      "parents": [
        {
          "id": "route-on-verdict",
          "branch": "on_refutes"
        },
        {
          "id": "impact-assessment"
        }
      ]
    }
  ]
}