{
  "hunt": {
    "meta": {
      "tlp": "clear",
      "hunt": {
        "handoff": "promote-to-detection",
        "trigger": "intel-report",
        "methodology": "model-assisted",
        "applicability": "campaign-specific",
        "justification": "Storm-3168 conducts extensive web reconnaissance before moving to destructive cloud operations; identifying these signals early allows for infrastructure blocking before initial access."
      },
      "name": "Storm-3168 Web Application Probing",
      "type": "investigation",
      "labels": [
        "hunt",
        "attack.t1595.002"
      ],
      "series": {
        "slug": "storm-3168-agentic-driven-cloud-attacks-using-compromised-service-principals",
        "index": 2,
        "title": "Storm-3168: Agentic-driven cloud attacks using compromised service principals",
        "total": 2
      },
      "related": [
        {
          "hunt": "storm-3168-cloud-resource-destruction",
          "reason": "Reconnaissance precedes the impact stage; that hunt monitors for resource deletion events.",
          "relation": "follows"
        },
        {
          "hunt": "storm-3168-azure-resource-destruction",
          "relation": "follows"
        }
      ],
      "targets": {
        "web": {
          "name": "Web server / proxy logs",
          "category": "siem",
          "telemetry": [
            "network"
          ]
        },
        "hunter": {
          "name": "Hunt agent",
          "agent": true
        },
        "analyst": {
          "name": "Tier-2 analyst",
          "role": "analyst"
        },
        "network": {
          "name": "Network telemetry",
          "category": "network",
          "telemetry": [
            "network"
          ]
        },
        "endpoint": {
          "name": "Endpoint telemetry (hb_ surfaces)",
          "category": "endpoint",
          "telemetry": [
            "endpoint"
          ]
        }
      },
      "analysis": "A standard detection rule alerts on the User Agent or sensitive paths. This hunt correlates those hits with wide scanning prevalence (targeting multiple hosts) and matches them against an organization's specific vulnerable asset inventory to reduce false positives and prioritize high-intent actors.",
      "coverage": [
        {
          "stage": "reconnaissance-application-probing",
          "steps": [
            "http-probing-lead",
            "ip-scanning-prevalence",
            "vulnerable-asset-inventory"
          ],
          "status": "covered"
        },
        {
          "stage": "initial-access-exposed-secret",
          "reason": "Belongs to a separate hunt focusing on GitHub audit logs and secret exposures.",
          "status": "out_of_scope"
        },
        {
          "stage": "reconnaissance-cloud-discovery",
          "reason": "Belongs to a separate hunt focusing on Azure Resource Manager enumeration via hb_cloud_api_activity.",
          "status": "out_of_scope"
        },
        {
          "stage": "impact-resource-deletion",
          "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "inhibit-recovery-lock-removal",
          "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "credential-access-storage-keys",
          "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 internet-facing web servers, WAFs, and application gateways. Priority is given to hosts already identified in hb_exposed_assets as running WordPress or AI-related tooling.",
      "guardrails": {
        "claims": "no_unsupported",
        "evidence": "citation_required",
        "telemetry": "untrusted",
        "missing_data": "not_benign"
      },
      "hypothesis": "An adversary is conducting automated web reconnaissance by probing for specific administrative and AI-related paths to identify vulnerable entry points for a subsequent cloud-focused intrusion.",
      "parameters": {
        "langflow_path": {
          "from": {
            "ref": "storm-3168-msrc",
            "kind": "article",
            "observed": "2026-09-25"
          },
          "type": "path",
          "default": "/api/v1/validate/code",
          "description": "The specific LangFlow code validation path."
        },
        "lookback_days": {
          "from": {
            "ref": "hunt-standard-lookback",
            "kind": "manual",
            "observed": "2026-09-25"
          },
          "type": "number",
          "default": "14",
          "description": "Days of history to examine."
        },
        "probing_paths": {
          "from": {
            "ref": "storm-3168-msrc",
            "kind": "article",
            "observed": "2026-09-25"
          },
          "type": "list[path]",
          "default": [
            "/wp-admin/",
            "/wp-login.php",
            "/php-cgi/"
          ],
          "description": "Sensitive paths targeted by Storm-3168 probing."
        },
        "storm_user_agent": {
          "from": {
            "ref": "storm-3168-msrc",
            "kind": "article",
            "observed": "2026-09-25"
          },
          "type": "string",
          "default": "python-requests/2.34.2",
          "description": "The specific User Agent observed during Storm-3168 activity."
        }
      },
      "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"
          ],
          "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": "MSRC \u2014 Storm-3168: Agentic-driven cloud attacks using compromised service principals"
        }
      ],
      "blind_spots": [
        {
          "id": "no-http-telemetry",
          "risk": "Probes against systems not reporting to central logging will be missed.",
          "stage": "reconnaissance-application-probing",
          "question": "whether probes targeted unmanaged or shadow IT assets",
          "requires": "hb_http_activity from all internet-facing servers"
        },
        {
          "id": "encrypted-traffic",
          "risk": "A successful probe (200 OK) might be an exploit attempt; without payload visibility, the hunt cannot confirm if code was actually executed.",
          "stage": "reconnaissance-application-probing",
          "question": "the specific content of POST request payloads",
          "requires": "TLS inspection or application-level logs"
        }
      ]
    },
    "name": "Storm-3168 Web Application Probing",
    "description": "This hunt identifies reconnaissance activity linked to Storm-3168 (JADEPUFFER), an actor known for agentic ransomware operations. The actor uses automated scripts to identify web-based entry points by probing for WordPress administrative paths, PHP-CGI vulnerabilities, and LangFlow code validation endpoints. The hunt filters HTTP telemetry for specific user agents and URI paths, then cross-references findings with source IP scanning prevalence and exposed asset context to distinguish directed actor activity from general internet background noise."
  },
  "nodes": [
    {
      "id": "hypothesis",
      "type": "hypothesis",
      "label": "Hypothesis",
      "config": {
        "tags": [],
        "series": {
          "slug": "storm-3168-agentic-driven-cloud-attacks-using-compromised-service-principals",
          "index": 2,
          "title": "Storm-3168: Agentic-driven cloud attacks using compromised service principals",
          "total": 2
        },
        "coverage": [
          {
            "stage": "reconnaissance-application-probing",
            "steps": [
              "http-probing-lead",
              "ip-scanning-prevalence",
              "vulnerable-asset-inventory"
            ],
            "status": "covered"
          },
          {
            "stage": "initial-access-exposed-secret",
            "reason": "Belongs to a separate hunt focusing on GitHub audit logs and secret exposures.",
            "status": "out_of_scope"
          },
          {
            "stage": "reconnaissance-cloud-discovery",
            "reason": "Belongs to a separate hunt focusing on Azure Resource Manager enumeration via hb_cloud_api_activity.",
            "status": "out_of_scope"
          },
          {
            "stage": "impact-resource-deletion",
            "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "inhibit-recovery-lock-removal",
            "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "credential-access-storage-keys",
            "reason": "Belongs to another part of the 'Storm-3168: Agentic-driven cloud attacks using compromised service principals' series.",
            "status": "out_of_scope"
          }
        ],
        "rationale": "An adversary is conducting automated web reconnaissance by probing for specific administrative and AI-related paths to identify vulnerable entry points for a subsequent cloud-focused intrusion.",
        "blind_spots": [
          {
            "id": "no-http-telemetry",
            "risk": "Probes against systems not reporting to central logging will be missed.",
            "stage": "reconnaissance-application-probing",
            "question": "whether probes targeted unmanaged or shadow IT assets",
            "requires": "hb_http_activity from all internet-facing servers"
          },
          {
            "id": "encrypted-traffic",
            "risk": "A successful probe (200 OK) might be an exploit attempt; without payload visibility, the hunt cannot confirm if code was actually executed.",
            "stage": "reconnaissance-application-probing",
            "question": "the specific content of POST request payloads",
            "requires": "TLS inspection or application-level logs"
          }
        ],
        "scoping_notes": "Focus on internet-facing web servers, WAFs, and application gateways. Priority is given to hosts already identified in hb_exposed_assets as running WordPress or AI-related tooling.",
        "beyond_detection": "A standard detection rule alerts on the User Agent or sensitive paths. This hunt correlates those hits with wide scanning prevalence (targeting multiple hosts) and matches them against an organization's specific vulnerable asset inventory to reduce false positives and prioritize high-intent actors."
      }
    },
    {
      "id": "http-probing-lead",
      "type": "query",
      "label": "HTTP probing for sensitive paths",
      "config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "source": "web",
        "content": "SELECT src_endpoint_ip, url_hostname, url_path, user_agent, status_code, http_method, time FROM hb_http_activity WHERE (LOWER(url_path) = LOWER('{{langflow_path}}') OR instr(',' || '{{probing_paths}}' || ',', ',' || LOWER(url_path) || ',') > 0 OR user_agent = '{{storm_user_agent}}') AND time >= datetime('now', '-{{lookback_days}} days')",
        "surface": "hb_http_activity",
        "description": "Identify HTTP requests matching known actor user agents or targeted vulnerability paths.",
        "expected_signal": "Requests matching the actor user agent or specific vulnerability paths. Hits on LangFlow or administrative paths with status 200 are high-interest."
      },
      "parents": [
        {
          "id": "hypothesis"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "label": "HTTP probing for sensitive paths",
        "reads": [
          "src_endpoint_ip",
          "url_hostname",
          "url_path",
          "user_agent",
          "status_code",
          "http_method",
          "time"
        ],
        "source": "hb_http_activity",
        "target": "web",
        "content": "SELECT src_endpoint_ip, url_hostname, url_path, user_agent, status_code, http_method, time FROM hb_http_activity WHERE (LOWER(url_path) = LOWER('{{langflow_path}}') OR instr(',' || '{{probing_paths}}' || ',', ',' || LOWER(url_path) || ',') > 0 OR user_agent = '{{storm_user_agent}}') AND time >= datetime('now', '-{{lookback_days}} days')",
        "silence": "not_evidence_of_absence",
        "expected": "Requests matching the actor user agent or specific vulnerability paths. Hits on LangFlow or administrative paths with status 200 are high-interest.",
        "verified": "dry-run",
        "verified_at": "2026-09-26"
      }
    },
    {
      "id": "ip-scanning-prevalence",
      "type": "query",
      "label": "Source IP scanning prevalence",
      "config": {
        "dsl": "sqlite",
        "role": "baseline",
        "source": "web",
        "content": "SELECT src_endpoint_ip, COUNT(DISTINCT url_hostname) AS host_targets, COUNT(*) AS request_hits, MIN(time) AS first_seen FROM hb_http_activity WHERE time >= datetime('now', '-{{lookback_days}} days') GROUP BY src_endpoint_ip HAVING host_targets > 1 ORDER BY host_targets DESC",
        "surface": "hb_http_activity",
        "description": "Stack-count source IPs to determine if they have targeted multiple distinct hostnames in the environment.",
        "expected_signal": "IPs targeting multiple hosts. Automated scanning is identified when host_targets exceeds normal per-IP limits."
      },
      "parents": [
        {
          "id": "http-probing-lead"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "baseline",
        "label": "Source IP scanning prevalence",
        "reads": [
          "src_endpoint_ip",
          "url_hostname",
          "time"
        ],
        "source": "hb_http_activity",
        "target": "web",
        "content": "SELECT src_endpoint_ip, COUNT(DISTINCT url_hostname) AS host_targets, COUNT(*) AS request_hits, MIN(time) AS first_seen FROM hb_http_activity WHERE time >= datetime('now', '-{{lookback_days}} days') GROUP BY src_endpoint_ip HAVING host_targets > 1 ORDER BY host_targets DESC",
        "silence": "not_evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "first_seen"
        },
        "expected": "IPs targeting multiple hosts. Automated scanning is identified when host_targets exceeds normal per-IP limits.",
        "verified": "dry-run",
        "prevalence": {
          "by": "url_hostname",
          "key": [
            "src_endpoint_ip"
          ],
          "rare_below": 2
        },
        "verified_at": "2026-09-26"
      }
    },
    {
      "id": "vulnerable-asset-inventory",
      "type": "query",
      "label": "Vulnerable asset inventory",
      "config": {
        "dsl": "sqlite",
        "role": "enrichment",
        "source": "endpoint",
        "content": "SELECT domain_or_ip, product, version, port FROM hb_exposed_assets WHERE product IS NOT NULL AND (LOWER(product) LIKE '%wordpress%' OR LOWER(product) LIKE '%php%' OR LOWER(product) LIKE '%langflow%')",
        "surface": "hb_exposed_assets",
        "description": "Identify hosts known to run WordPress, PHP, or LangFlow to confirm the relevance of the probes.",
        "expected_signal": "A list of hosts running products the actor is actively probing. Probes against these specific hosts indicate targeted intent."
      },
      "parents": [
        {
          "id": "http-probing-lead"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "enrichment",
        "label": "Vulnerable asset inventory",
        "reads": [
          "domain_or_ip",
          "product",
          "version",
          "port"
        ],
        "source": "hb_exposed_assets",
        "target": "endpoint",
        "content": "SELECT domain_or_ip, product, version, port FROM hb_exposed_assets WHERE product IS NOT NULL AND (LOWER(product) LIKE '%wordpress%' OR LOWER(product) LIKE '%php%' OR LOWER(product) LIKE '%langflow%')",
        "silence": "not_evidence_of_absence",
        "expected": "A list of hosts running products the actor is actively probing. Probes against these specific hosts indicate targeted intent.",
        "verified": "dry-run",
        "verified_at": "2026-09-26"
      }
    },
    {
      "id": "agent-triage",
      "type": "analytic",
      "label": "Evaluate probing activity",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint",
          "web"
        ],
        "context": [
          "http-probing-lead",
          "ip-scanning-prevalence",
          "vulnerable-asset-inventory"
        ],
        "objective": "Determine if source IPs are conducting targeted Storm-3168 application probing based on user agent, paths, status codes, scanning prevalence, and the presence of vulnerable software on the targets.",
        "description": "Synthesize the HTTP hits, scanning prevalence, and asset inventory to determine the maliciousness of source IPs.",
        "max_iterations": 4,
        "expected_signal": "A malicious/suspicious/benign verdict per source IP citing relevant rows.",
        "success_criteria": "Verdicts for each suspect IP, identifying those that hit vulnerable assets with the Storm-3168 user agent or paths."
      },
      "parents": [
        {
          "id": "ip-scanning-prevalence",
          "kind": "merge"
        },
        {
          "id": "vulnerable-asset-inventory",
          "kind": "merge"
        }
      ]
    },
    {
      "id": "route-on-verdict",
      "type": "checkpoint",
      "label": "Route on verdict",
      "config": {
        "fuzzy": true,
        "judge": "hunter",
        "question": "the agent-triage verdict is malicious for at least one source IP conducting automated probes against WordPress or LangFlow assets",
        "condition": "the agent-triage verdict is malicious for at least one source IP conducting automated probes against WordPress or LangFlow assets",
        "blind_spot": "no-http-telemetry",
        "confidence": "high",
        "description": "Branch the hunt based on the agent's confidence in the malicious probing activity.",
        "checkpoint_type": "mandatory"
      },
      "parents": [
        {
          "id": "agent-triage"
        }
      ]
    },
    {
      "id": "block-attacker-ip",
      "type": "action",
      "label": "Block attacker IP",
      "config": {
        "target": "network",
        "description": "Immediately mitigate the threat by blocking identified actor infrastructure at the network perimeter.",
        "instructions": "Block the identified source IPs in the WAF, perimeter firewall, or application gateway to prevent further reconnaissance or exploitation.",
        "action_approval": "required"
      },
      "parents": [
        {
          "id": "route-on-verdict",
          "branch": "on_supports"
        }
      ]
    },
    {
      "id": "analyst-confirmation",
      "type": "task",
      "label": "Analyst confirmation",
      "config": {
        "assignee": "analyst",
        "description": "Verify the agent's findings and assess whether probes resulted in successful exploitation attempts.",
        "instructions": "Review the full HTTP request logs for the identified IPs. Check for subsequent POST requests to administrative or code-validation paths that might indicate successful exploitation. Validate the product version on the target hosts."
      },
      "parents": [
        {
          "id": "route-on-verdict",
          "branch": "default"
        },
        {
          "id": "route-on-verdict",
          "branch": "on_unavailable"
        },
        {
          "id": "route-on-verdict",
          "branch": "on_refutes"
        },
        {
          "id": "block-attacker-ip"
        }
      ]
    },
    {
      "id": "hunt-close-out",
      "type": "task",
      "label": "Hunt close-out",
      "config": {
        "assignee": "analyst",
        "description": "Document the findings and recommend standing detections.",
        "instructions": "Record the identified IPs and the targeted paths. If successful probes were found against vulnerable versions of WordPress or LangFlow, ensure those systems are patched and credentials rotated."
      },
      "parents": [
        {
          "id": "analyst-confirmation"
        }
      ]
    }
  ]
}