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
-
Identify vulnerable internet-facing hosts
Query · scopingFocus the hunt on instances with known high or critical vulnerabilities by joining vulnerability findings with device inventory to get hostnames.
reads hb_vulnerability_findingsqlSELECT 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.providerWhat 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.
-
Successful web application exploitation
Query · triageIdentify successful HTTP requests to sensitive paths or those resulting in errors that suggest attempts to exploit web vulnerabilities.
reads hb_http_activitysqlSELECT 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_ipWhat a hit looks like. Requests resulting in status 200 for sensitive system files or cloud metadata, indicating potential successful exploitation.
-
Anomalous shell spawns from web processes
Query · detection candidateDetect successful exploitation by finding shells spawned by web servers or other user-facing applications.
reads hb_process_activitysqlSELECT 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.
-
In-memory or encoded script activity
Query · triageCapture encoded or in-memory execution which frequently follows initial exploitation to obfuscate post-compromise activity.
reads hb_script_activitysqlSELECT 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.
-
Identify host-associated cloud identities
Query · enrichmentIdentify the IAM role or user associated with the scoped hosts to look for signs of identity drift.
reads hb_auth_signinsqlSELECT 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.
-
Weigh compromise evidence and identity drift
Agent triageCorrelate vulnerability state, HTTP traffic patterns, process execution, and script content to determine if a host identity has drifted from its profile.
-
Route based on compromise verdict
DecisionIsolate hosts with confirmed compromise while routing uncertain cases to manual analyst review.
-
Isolate host and revoke sessions
Response actionSever the adversary's foothold to prevent them from using the host's identity to access cloud APIs.
-
Analyze forensic evidence and identity logs
Analyst taskReview forensic artifacts and cloud audit logs to confirm the extent of the identity's misuse.
-
Close out and remediate vulnerabilities
Analyst taskDocument findings and ensure the root cause vulnerability is patched.
Coverage
Scenario coverage
| Stage | Covered | How, 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
| Parameter | Type | Default | What it is |
|---|---|---|---|
lookback_days | number | 14 | Days of history to examine for active behavior. |
scope_hosts | list[host] | — | Hostnames derived from the scoping step; leave empty to scan the full estate. |
sensitive_paths | list[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_processes | list[string] | cmd.exe, powershell.exe, pwsh.exe, sh, bash, nc, curl, wget | Shells and network tools that indicate post-exploitation activity. |
web_parent_processes | list[string] | httpd, nginx, w3wp.exe, apache2, php-fpm, chrome.exe, msedge.exe, outlook.exe | Parent processes commonly exploited or used to launch malicious payloads. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Identity / sign-in telemetry | identity | identity |
| Web server / proxy logs | siem | network |
Source
---
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.