← All hunts medium TLP:CLEAR Part 1 of 2

Public app exploitation and cloud identity drift

An adversary has exploited a public-facing application on a cloud instance to obtain its identity, which is now being used for activity that deviates from the host's established behavioral profile.

Based on research by Unit 42 2026-09-20 11 steps · 5 queries T1078.004 T1190 T1204.002

Brief

The Context

Cloud intrusions often start at the edge. Attackers target public-facing applications to gain a foothold, but their true objective is often the underlying service identity. Once an adversary co-opts a cloud role, they can move laterally through the control plane, often bypassing traditional perimeter defenses. This hunt builds on research from Unit 42 titled "Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection" (https://unit42.paloaltonetworks.com/behavioral-clustering-map-to-cloud-identities/), which explores how cloud identities follow predictable behavioral patterns.

How the Hunt Flows

The first query identifies the attack surface. It filters the inventory for cloud instances that are internet-facing and host high or critical vulnerabilities. This scoping step ensures the hunt focuses on the most likely targets for initial access.

The second phase runs four queries in parallel to collect evidence. One query monitors HTTP activity for successful requests to sensitive paths like metadata endpoints or configuration files. Simultaneously, another query searches for shells spawned by web server processes like Nginx or Apache. A third query captures encoded script activity that often follows exploitation, while the fourth retrieves the IAM sign-in context to see which identity the host is currently using.

The final phase correlates these findings. An analyst evaluates whether the observed behavior aligns with the host functional role. If a backup service identity suddenly begins enumerating cloud storage or a web server spawns a shell to curl external sites, the hunt flags this as identity drift.

Blind Spots and Limitations

This hunt has two primary blind spots. First, it relies on HTTP metadata. Because the telemetry lacks request bodies, an analyst cannot always see the specific payload in a successful POST request. This makes it difficult to distinguish between legitimate API use and a sophisticated exploit. Second, the hunt requires endpoint telemetry. If an adversary compromises a host that lacks a security agent, the hunt loses visibility into process execution and script activity, leaving only the network and identity logs for analysis.

Running the Hunt

This hunt is a hunt.md playbook. You can import it into Huntbase or any runtime that supports the hunt.md format. It uses parameters for lookback windows and sensitive path lists, allowing for tuning based on your environment. Running this hunt validates the integrity of your internet-exposed hosts and ensures that your service identities remain within their expected operational boundaries.

In this series

Steps

  1. Identify vulnerable internet-facing hosts

    Query · scoping

    Focus the hunt on instances with known high or critical vulnerabilities by joining vulnerability findings with device inventory to get hostnames.

    reads hb_vulnerability_findingsql
    SELECT DISTINCT d.hostname AS device_hostname, v.cve_uid, v.title FROM hb_vulnerability_finding v JOIN hb_devices d ON v.device_uid = d.device_uid WHERE v.severity_id >= 4 AND v.resource_type = 'instance' AND v.status != 'suppressed' AND v.provider = d.provider

    What a hit looks like. A list of hostnames for cloud instances with critical vulnerabilities. If empty, the estate has no current high-risk exposures to focus on.

  2. Successful web application exploitation

    Query · triage

    Identify successful HTTP requests to sensitive paths or those resulting in errors that suggest attempts to exploit web vulnerabilities.

    reads hb_http_activitysql
    SELECT device_hostname, url_path, status_code, src_endpoint_ip, COUNT(*) as total_requests FROM hb_http_activity WHERE (status_code = 200 OR status_code >= 400) AND (instr(',' || '{{sensitive_paths}}' || ',', ',' || LOWER(url_path) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, url_path, status_code, src_endpoint_ip

    What a hit looks like. Requests resulting in status 200 for sensitive system files or cloud metadata, indicating potential successful exploitation.

  3. Anomalous shell spawns from web processes

    Query · detection candidate

    Detect successful exploitation by finding shells spawned by web servers or other user-facing applications.

    reads hb_process_activitysql
    SELECT device_hostname, process_name, process_cmd_line, parent_process_name, user_name, time FROM hb_process_activity WHERE (instr(',' || '{{web_parent_processes}}' || ',', ',' || LOWER(parent_process_name) || ',') > 0) AND (instr(',' || '{{shell_processes}}' || ',', ',' || LOWER(process_name) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. A shell running under a web server context (e.g., www-data) following a web request.

  4. In-memory or encoded script activity

    Query · triage

    Capture encoded or in-memory execution which frequently follows initial exploitation to obfuscate post-compromise activity.

    reads hb_script_activitysql
    SELECT device_hostname, script_name, script_content, actor_user_name, time FROM hb_script_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Encoded script blocks or suspicious PowerShell/Shell script content on potentially compromised hosts.

  5. Identify host-associated cloud identities

    Query · enrichment

    Identify the IAM role or user associated with the scoped hosts to look for signs of identity drift.

    reads hb_auth_signinsql
    SELECT actor_user_name, src_endpoint_ip, dst_endpoint_name, auth_protocol, time FROM hb_auth_signin WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || dst_endpoint_name || ',') > 0 OR instr(',' || '{{scope_hosts}}' || ',', ',' || src_endpoint_ip || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. The IAM identities used by or signing into the target hosts, providing context for behavioral role analysis.

  6. Weigh compromise evidence and identity drift

    Agent triage

    Correlate vulnerability state, HTTP traffic patterns, process execution, and script content to determine if a host identity has drifted from its profile.

  7. Route based on compromise verdict

    Decision

    Isolate hosts with confirmed compromise while routing uncertain cases to manual analyst review.

  8. Isolate host and revoke sessions

    Response action

    Sever the adversary's foothold to prevent them from using the host's identity to access cloud APIs.

  9. Analyze forensic evidence and identity logs

    Analyst task

    Review forensic artifacts and cloud audit logs to confirm the extent of the identity's misuse.

  10. Close out and remediate vulnerabilities

    Analyst task

    Document findings and ensure the root cause vulnerability is patched.

Coverage

Scenario coverage

StageCoveredHow, or why not
Exploitation of Public-Facing Application
T1190
Yes high-risk-vulnerable-hosts, web-exploitation-indicators
User Execution of Malicious File
T1204.002
Yes suspicious-shell-spawns, encoded-script-execution
Cloud Identity Authentication Out of scope Belongs to another part of the 'Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection' series.
Cloud Resource Discovery Out of scope Belongs to another part of the 'Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection' series.
Multi-hop Proxy Obfuscation
T1090.003
Out of scope Belongs to another part of the 'Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection' series.

Blind spots

  • Needs WAF or local server logs with body content. hb_http_activity lacks request bodies, making it hard to distinguish between legitimate API usage and exploitation on success. It would answer whether the specific payload in a successful POST request was malicious.
  • Needs hb_process_activity from an endpoint agent. A host without an agent provides no process or script visibility, leaving the hunt blind to the follow-on execution. It would answer whether a shell was spawned on a host missing the telemetry agent.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
lookback_daysnumber14Days of history to examine for active behavior.
scope_hostslist[host]Hostnames derived from the scoping step; leave empty to scan the full estate.
sensitive_pathslist[string]/etc/passwd, /etc/shadow, /wp-admin/, /cgi-bin/, /.env, /config.php, /aws/config, /metadata/latest/Web paths frequently targeted by directory traversal or cloud metadata theft.
shell_processeslist[string]cmd.exe, powershell.exe, pwsh.exe, sh, bash, nc, curl, wgetShells and network tools that indicate post-exploitation activity.
web_parent_processeslist[string]httpd, nginx, w3wp.exe, apache2, php-fpm, chrome.exe, msedge.exe, outlook.exeParent processes commonly exploited or used to launch malicious payloads.

Telemetry

SourceCategoryTelemetry
Endpoint telemetry (hb_ surfaces)endpointendpoint
Identity / sign-in telemetryidentityidentity
Web server / proxy logssiemnetwork

Source

Download hunt.md Definition (JSON) An open hunt.md file; it runs anywhere that reads the format.
---
analysis: While a detection rule might fire on a shell, it lacks the context of identity
  role drift. This hunt correlates vulnerability data, successful HTTP exploitation,
  and IAM sign-in context to evaluate behavior against a host's functional profile.
blind_spots:
- id: no-http-body-telemetry
  question: whether the specific payload in a successful POST request was malicious
  requires: WAF or local server logs with body content
  risk: hb_http_activity lacks request bodies, making it hard to distinguish between
    legitimate API usage and exploitation on success.
  stage: exploit-public-application
- id: no-endpoint-telemetry
  question: whether a shell was spawned on a host missing the telemetry agent
  requires: hb_process_activity from an endpoint agent
  risk: A host without an agent provides no process or script visibility, leaving
    the hunt blind to the follow-on execution.
  stage: client-side-execution
coverage:
- stage: exploit-public-application
  status: covered
  steps:
  - high-risk-vulnerable-hosts
  - web-exploitation-indicators
- stage: client-side-execution
  status: covered
  steps:
  - suspicious-shell-spawns
  - encoded-script-execution
- reason: 'Belongs to another part of the ''Unmasking Cloud Identities: From Behavioral
    Clustering to Automated Detection'' series.'
  stage: cloud-identity-authentication
  status: out_of_scope
- reason: 'Belongs to another part of the ''Unmasking Cloud Identities: From Behavioral
    Clustering to Automated Detection'' series.'
  stage: cloud-resource-discovery
  status: out_of_scope
- reason: 'Belongs to another part of the ''Unmasking Cloud Identities: From Behavioral
    Clustering to Automated Detection'' series.'
  stage: multi-hop-proxy-obfuscation
  status: out_of_scope
guardrails:
  claims: no_unsupported
  evidence: citation_required
  missing_data: not_benign
  telemetry: untrusted
hunt:
  applicability: campaign-specific
  handoff: promote-to-detection
  justification: Exploitation of public-facing applications is the primary entry point
    for gaining the identities needed for cloud intrusions. A negative result validates
    the organization's perimeter integrity and the stability of its service identities.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An adversary has exploited a public-facing application on a cloud instance
  to obtain its identity, which is now being used for activity that deviates from
  the host's established behavioral profile.
labels:
- hunt
- attack.t1190
- attack.t1204.002
- attack.t1078.004
name: Public app exploitation and cloud identity drift
parameters:
  lookback_days:
    default: '14'
    description: Days of history to examine for active behavior.
    type: number
  scope_hosts:
    default: []
    description: Hostnames derived from the scoping step; leave empty to scan the
      full estate.
    type: list[host]
  sensitive_paths:
    default:
    - /etc/passwd
    - /etc/shadow
    - /wp-admin/
    - /cgi-bin/
    - /.env
    - /config.php
    - /aws/config
    - /metadata/latest/
    description: Web paths frequently targeted by directory traversal or cloud metadata
      theft.
    type: list[string]
  shell_processes:
    default:
    - cmd.exe
    - powershell.exe
    - pwsh.exe
    - sh
    - bash
    - nc
    - curl
    - wget
    description: Shells and network tools that indicate post-exploitation activity.
    type: list[string]
  web_parent_processes:
    default:
    - httpd
    - nginx
    - w3wp.exe
    - apache2
    - php-fpm
    - chrome.exe
    - msedge.exe
    - outlook.exe
    description: Parent processes commonly exploited or used to launch malicious payloads.
    type: list[string]
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://unit42.paloaltonetworks.com/behavioral-clustering-map-to-cloud-identities/
    gates:
    - dry-run
    - lint
    model: hb_google/gemini-3-flash-preview
rationale: Focus on cloud instances with High or Critical vulnerabilities first. The
  scoping query uses a join to provide hostnames for the scope_hosts parameter. If
  no vulnerabilities are reported, widen the scope to all hosts with internet exposure
  found in hb_exposed_assets.
references:
- name: "Unit 42 \u2014 Unmasking Cloud Identities: From Behavioral Clustering to\
    \ Automated Detection"
  url: https://unit42.paloaltonetworks.com/behavioral-clustering-map-to-cloud-identities/
related:
- hunt: cloud-identity-behavioral-anomaly
  reason: This hunt identifies the initial compromise; the follow-on hunt examines
    broader identity misuse within the cloud control plane.
  relation: follows
scenario:
  stages:
  - name: Exploitation of Public-Facing Application
    observables:
    - Inbound exploitation attempts against internet-facing web servers
    - Unauthorized HTTP POST requests to vulnerable endpoints
    slug: exploit-public-application
    tactic: initial-access
    techniques:
    - T1190
  - name: User Execution of Malicious File
    observables:
    - Execution of downloaded suspicious documents or binaries
    - Process spawning from browser or email client
    - Malicious file creation in temporary directories
    slug: client-side-execution
    tactic: execution
    techniques:
    - T1204.002
  - name: Cloud Identity Authentication
    observables:
    - ConsoleLogin events
    - GetSigninToken activity
    - Identity naming patterns containing 'admin'
    - AWSReservedSSO_AdministratorAccess_ prefix usage
    slug: cloud-identity-authentication
    tactic: initial-access
  - name: Cloud Resource Discovery
    observables:
    - ListBuckets
    - ListRoles
    - ListNotificationHubs
    - GetCostAndUsage
    - GetCostForecast
    slug: cloud-resource-discovery
    tactic: discovery
  - name: Multi-hop Proxy Obfuscation
    observables:
    - Sign-in activity from known Tor exit nodes
    - Network connections to multi-hop VPS or ORB networks
    - Anomalous source IP addresses for administrative sessions
    slug: multi-hop-proxy-obfuscation
    tactic: command-and-control
    techniques:
    - T1090.003
  summary: Attackers leverage exploited applications or social engineering to gain
    access to over-privileged cloud identities, which are then used to perform resource
    enumeration and discovery within AWS Management Console. To evade detection, actors
    masquerade using benign permission profiles and mask their activity source through
    multi-hop proxies or Tor, requiring behavioral clustering to distinguish malicious
    reconnaissance from legitimate administrative activity.
series:
  index: 1
  slug: unmasking-cloud-identities-from-behavioral-clustering-to-automated-detection
  title: 'Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection'
  total: 2
severity: medium
targets:
  analyst:
    name: Tier-2 analyst
    role: analyst
  endpoint:
    category: endpoint
    name: Endpoint telemetry (hb_ surfaces)
    telemetry:
    - endpoint
  hunter:
    agent: true
    name: Hunt agent
  identity:
    category: identity
    name: Identity / sign-in telemetry
    telemetry:
    - identity
  web:
    category: siem
    name: Web server / proxy logs
    telemetry:
    - network
tlp: clear
type: investigation
---


# Public app exploitation and cloud identity drift

This hunt identifies the initial entry points of a cloud-focused intrusion by examining internet-exposed hosts for vulnerabilities, successful web exploitation, and follow-on shell activity. Building on Unit 42 research regarding behavioral clustering of cloud identities, the hunt evaluates whether the activity observed on a compromised host aligns with its functional role. By correlating HTTP traffic, anomalous process execution, and the underlying IAM identity, analysts can detect when a service role has been co-opted for malicious discovery or lateral movement.

## high-risk-vulnerable-hosts
<!-- Identify vulnerable internet-facing hosts -->
Focus the hunt on instances with known high or critical vulnerabilities by joining vulnerability findings with device inventory to get hostnames.

```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hostnames for cloud instances with critical vulnerabilities. If
  empty, the estate has no current high-risk exposures to focus on.
reads:
- v.device_uid
- d.device_uid
- d.hostname
- v.severity_id
- v.resource_type
- v.status
- v.provider
- d.provider
silence: not_evidence_of_absence
source: hb_vulnerability_finding
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT DISTINCT d.hostname AS device_hostname, v.cve_uid, v.title FROM hb_vulnerability_finding v JOIN hb_devices d ON v.device_uid = d.device_uid WHERE v.severity_id >= 4 AND v.resource_type = 'instance' AND v.status != 'suppressed' AND v.provider = d.provider
```

## exploitation-fan-out
<!-- Analyze traffic and execution in parallel -->
parallel:
- → web-exploitation-indicators
- → suspicious-shell-spawns
- → encoded-script-execution
- → host-identity-context
join: → triage-compromise

## web-exploitation-indicators
<!-- Successful web application exploitation -->
Identify successful HTTP requests to sensitive paths or those resulting in errors that suggest attempts to exploit web vulnerabilities.

```sqlite target=web role=triage params=(sensitive_paths=sensitive_paths, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: Requests resulting in status 200 for sensitive system files or cloud metadata,
  indicating potential successful exploitation.
reads:
- device_hostname
- url_path
- status_code
- src_endpoint_ip
- time
silence: not_evidence_of_absence
source: hb_http_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, url_path, status_code, src_endpoint_ip, COUNT(*) as total_requests FROM hb_http_activity WHERE (status_code = 200 OR status_code >= 400) AND (instr(',' || '{{sensitive_paths}}' || ',', ',' || LOWER(url_path) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, url_path, status_code, src_endpoint_ip
```

## suspicious-shell-spawns
<!-- Anomalous shell spawns from web processes -->
Detect successful exploitation by finding shells spawned by web servers or other user-facing applications.

```sqlite target=endpoint role=detection-candidate params=(web_parent_processes=web_parent_processes, shell_processes=shell_processes, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: A shell running under a web server context (e.g., www-data) following a
  web request.
reads:
- device_hostname
- process_name
- process_cmd_line
- parent_process_name
- user_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_name, process_cmd_line, parent_process_name, user_name, time FROM hb_process_activity WHERE (instr(',' || '{{web_parent_processes}}' || ',', ',' || LOWER(parent_process_name) || ',') > 0) AND (instr(',' || '{{shell_processes}}' || ',', ',' || LOWER(process_name) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## encoded-script-execution
<!-- In-memory or encoded script activity -->
Capture encoded or in-memory execution which frequently follows initial exploitation to obfuscate post-compromise activity.

```sqlite target=endpoint role=triage params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: Encoded script blocks or suspicious PowerShell/Shell script content on potentially
  compromised hosts.
reads:
- device_hostname
- script_name
- script_content
- actor_user_name
- time
silence: not_evidence_of_absence
source: hb_script_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, script_name, script_content, actor_user_name, time FROM hb_script_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## host-identity-context
<!-- Identify host-associated cloud identities -->
Identify the IAM role or user associated with the scoped hosts to look for signs of identity drift.

```sqlite target=identity role=enrichment params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: The IAM identities used by or signing into the target hosts, providing context
  for behavioral role analysis.
reads:
- actor_user_name
- src_endpoint_ip
- dst_endpoint_name
- auth_protocol
- time
silence: not_evidence_of_absence
source: hb_auth_signin
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT actor_user_name, src_endpoint_ip, dst_endpoint_name, auth_protocol, time FROM hb_auth_signin WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || dst_endpoint_name || ',') > 0 OR instr(',' || '{{scope_hosts}}' || ',', ',' || src_endpoint_ip || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## triage-compromise
<!-- Weigh compromise evidence and identity drift -->
```agent target=hunter
cite: required
context:
- high-risk-vulnerable-hosts
- web-exploitation-indicators
- suspicious-shell-spawns
- encoded-script-execution
- host-identity-context
max_iterations: 5
objective: "Determine if any vulnerable host shows signs of successful exploitation.\
  \ Explicitly look for 'identity role drift'\u2014comparing the actions taken by\
  \ the compromised host's IAM role (found in host-identity-context) against its typical\
  \ activity profile (e.g., a backup service suddenly spawning shells or a developer\
  \ role accessing restricted web paths)."
success_criteria: A detailed verdict citing specific HTTP requests and shell commands
  for each host, highlighting drift from the identity's known role.
tools:
- endpoint
- identity
- web
```

## route-on-compromise
<!-- Route based on compromise verdict -->
if~: "the triage verdict is malicious for at least one host showing overlapping signals of exploitation and identity drift" (confidence: high, judge=hunter)
then: → isolate-compromised-host
indeterminate: → manual-investigation
unavailable: → manual-investigation (blind_spot: no-endpoint-telemetry)
else: → close-out-investigation

## isolate-compromised-host
<!-- Isolate host and revoke sessions -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host at the network level and terminate all active user sessions associated with its identity profile.
```
→ manual-investigation

## manual-investigation
<!-- Analyze forensic evidence and identity logs -->
```manual target=analyst
Examine the host's activity in AWS CloudTrail to verify if it performed operations outside of its established behavioral cluster.
```
→ close-out-investigation

## close-out-investigation
<!-- Close out and remediate vulnerabilities -->
```manual target=analyst
Patch the vulnerable application and document the behavioral indicators observed for future tuning of the identity clustering model.
```
→ end

Run it

Take this hunt into your environment.

Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.

Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.