Integrator Supply Chain Compromise and SCADA Data Exfiltration
A malicious actor has pivoted from a compromised third-party integrator network into the ICS environment, searched for SCADA schematics using sensitive keywords, and staged them in archives for exfiltration.
Based on research by CISA 2026-09-24 13 steps · 6 queries T1041 T1083 T1190 T1195 T1560
Brief
Why Now
CISA recently published an advisory titled "Considerations for Critical Infrastructure Operators Working With Third-Party ICS Integrators" (https://www.cisa.gov/resources-tools/resources/considerations-critical-infrastructure-operators-working-third-party-ics-integrators) which highlights a critical vulnerability in the industrial supply chain. Threat actors are increasingly targeting the networks of third-party integrators to gain a foothold in the environments of their customers. Because these integrators often manage industrial control systems (ICS) and SCADA networks across multiple sectors—including power, water, and transportation—a single compromise at the integrator level can lead to widespread access to sensitive national infrastructure. This hunt provides a systematic approach to identifying and investigating these pivots before an adversary can cause operational disruption or steal proprietary engineering data.
How the Hunt Flows
The hunt begins with an initial scoping phase to identify internet-exposed assets. We catalog every external-facing service and jump host, as these represent the most likely entry points for an integrator. This inventory allows the hunt to focus its analysis on the systems that are most vulnerable to an external supply chain pivot, ensuring that subsequent queries are both targeted and efficient.
Next, the hunt triages early access markers across authentication and network surfaces. We check for successful logins that originate from known integrator IP ranges or general external locations. Parallel queries identify anomalous inbound network sessions that might indicate the exploitation of a public application. An automated agent then analyzes these results to determine if any host in the scope shows signs of a suspicious beachhead.
If the triage identifies a potential breach, the hunt fans out to look for follow-on behavior. We monitor file activity on the suspect hosts, specifically looking for the use of keywords like "SCADA", "schematic", "PLC", or "customer". This activity mirrors the behavior of an adversary searching for sensitive engineering documents once they have established access.
Simultaneously, we analyze the prevalence of archive creation across the environment. The hunt looks for processes that create multiple .zip or .7z files, focusing on those that are rare for a specific host or process. This identifies the staging phase where an actor prepares data for exfiltration. We distinguish these events from normal maintenance by baseline analysis of common process behavior.
The final data gathering phase focuses on exfiltration traffic. We sum outbound bytes sent to external IP addresses to identify traffic peaks that match the expected size of the staged data. A final agent then evaluates the full chain of evidence—from the initial login to the final outbound transfer—to provide a high-confidence verdict for the analyst.
What the Hunt Cannot See
This hunt has two primary blind spots. First, it depends on endpoint-based telemetry for process and file monitoring. If an adversary moves directly from a compromised workstation to a legacy ICS controller using a proprietary industrial protocol, the activity may not be captured by standard endpoint logs. Second, the hunt identifies the volume of exfiltration but cannot confirm the specific content of the traffic without deep packet inspection or TLS decryption.
Steps
-
Identify internet-exposed assets
Query · scopingFind the assets that are externally reachable and serve as the most likely pivot points from an integrator.
reads hb_exposed_assetssqlSELECT domain_or_ip, product, asset_type, port FROM hb_exposed_assets WHERE asset_type = 'service'What a hit looks like. A list of hostnames or IPs with internet exposure. Silence means no assets are currently cataloged as exposed.
-
Authentication from integrator sources
Query · enrichmentCheck for successful logins from the integrator's network or external sources into the estate.
reads hb_auth_signinsqlSELECT actor_user_name, src_endpoint_ip, dst_endpoint_name, time FROM hb_auth_signin WHERE status_id = 1 AND ('{{integrator_ips}}' = '' OR instr(',' || '{{integrator_ips}}' || ',', ',' || src_endpoint_ip || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Rows mapping users and IPs to successful logins. If integrator_ips is empty, any external-to-internal successful auth is returned.
-
Anomalous inbound network sessions
Query · enrichmentIdentify inbound log sessions from external IPs that might signify exploitation of a public application.
reads hb_network_connectionsqlSELECT device_hostname, src_endpoint_ip, dst_endpoint_port, time FROM hb_network_connection WHERE direction = 'inbound' AND state_kind = 'log' AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Evidence of external IP addresses establishing connections to internal endpoints.
-
Triaging early access
Agent triageAnalyze whether any host from the scoping inventory shows active sign-in or connection markers from the integrator's direction.
-
Sensitive keyword file access
Query · detection candidateDetect an actor searching for SCADA schematics or customer data as mentioned in the advisory.
reads hb_file_activitysqlSELECT device_hostname, file_name, file_path, process_name, time FROM hb_file_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND instr(',' || '{{scada_keywords}}' || ',', ',' || LOWER(file_name) || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. A process accessing or creating files with keywords like 'SCADA' or 'customer'. None means those exact terms were not observed in filenames.
-
Rare archive creation prevalence
Query · baselineFind the staging of multiple files into archives, which is rare across the fleet.
reads hb_file_activitysqlSELECT device_hostname, process_name, COUNT(DISTINCT file_path) AS archive_count, MIN(time) AS first_seen FROM hb_file_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND (LOWER(file_path) LIKE '%.zip' OR LOWER(file_path) LIKE '%.7z') AND activity_id = 1 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name HAVING archive_count > 1What a hit looks like. A host where a process creates multiple archives. Baseline analysis highlights those that are rare.
-
Exfiltration traffic peaks
Query · enrichmentIdentify significant outbound data transfers that match the expected staging size.
reads hb_network_connectionsqlSELECT device_hostname, dst_endpoint_ip, SUM(traffic_bytes) AS total_bytes FROM hb_network_connection WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND direction = 'outbound' AND state_kind = 'log' AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, dst_endpoint_ip HAVING total_bytes > 5000000What a hit looks like. A host sending more than 5MB of data to an external IP. Silence proofs absence of large transfers to single destinations.
-
Full chain verdict
Agent triageCombine the early access triage with the follow-on discovery and exfiltration evidence to determine if a breach occurred.
-
Route on full verdict
DecisionDirect the response based on the agent's judgment of the attack chain.
-
Contain suspected host
Response actionIsolate the host to prevent further exfiltration or lateral movement.
-
Analyst final review
Analyst taskValidate the findings and prepare the IR handoff.
-
Close out hunt
Analyst taskRecord the coverage and negative findings.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| Supply Chain or Exploit Access T1195 · T1190 |
Yes | exposed-asset-inventory, auth-logins-from-integrators, external-inbound-connections |
| File and Keyword Discovery T1083 |
Yes | discovery-by-keywords |
| Data Staging in ZIP Archives T1560 |
Yes | archive-creation-prevalence |
| Exfiltration over C2 T1041 |
Yes | exfiltration-traffic-peaks |
Blind spots
- Needs Endpoint telemetry on legacy ICS controllers. An actor moving directly to a controller via a legacy protocol may be invisible to endpoint-based file and process monitoring. It would answer Are the PLC or SCADA controllers themselves logging process and file activity?.
- Needs DPI or TLS inspection. The hunt relies on byte counts; without inspection, we cannot prove the content of the transfer. It would answer Are the network connections carrying the staged ZIP files or benign maintenance data?.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
integrator_ips | list[ip] | — | Known IP ranges of third-party integrators; if empty, the hunt checks all external successes. |
lookback_days | number | 14 | Days of history to examine. |
scada_keywords | list[string] | scada, customer, customers, schematic, plc, diagram | Keywords potentially used in filenames during the discovery phase. |
scope_hosts | list[host] | — | Hosts identified in the scoping query to narrow the second-stage search. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Identity / sign-in telemetry | identity | identity |
| Network telemetry | network | network |
Source
---
analysis: A single detection rule cannot correlate the internet-exposed scoping with
specific sensitive keyword discovery and rare archive staging behavior; this hunt
uses three telemetry surfaces and a phased flow to distinguish a breach from normal
engineering maintenance.
blind_spots:
- id: limited-endpoint-visibility
question: Are the PLC or SCADA controllers themselves logging process and file activity?
requires: Endpoint telemetry on legacy ICS controllers
risk: An actor moving directly to a controller via a legacy protocol may be invisible
to endpoint-based file and process monitoring.
stage: initial-access-integrator-pivot
- id: exfil-payload-opacity
question: Are the network connections carrying the staged ZIP files or benign maintenance
data?
requires: DPI or TLS inspection
risk: The hunt relies on byte counts; without inspection, we cannot prove the content
of the transfer.
stage: exfiltration-c2-channel
coverage:
- stage: initial-access-integrator-pivot
status: covered
steps:
- exposed-asset-inventory
- auth-logins-from-integrators
- external-inbound-connections
- stage: discovery-sensitive-keywords
status: covered
steps:
- discovery-by-keywords
- stage: collection-archive-staging
status: covered
steps:
- archive-creation-prevalence
- stage: exfiltration-c2-channel
status: covered
steps:
- exfiltration-traffic-peaks
guardrails:
claims: no_unsupported
evidence: citation_required
missing_data: not_benign
telemetry: untrusted
hunt:
applicability: campaign-specific
handoff: promote-to-detection
justification: Protecting critical infrastructure from supply chain compromise is
a primary obligation; this hunt validates the integrity of integrator access to
sensitive SCADA data.
methodology: model-assisted
trigger: intel-report
hypothesis: A malicious actor has pivoted from a compromised third-party integrator
network into the ICS environment, searched for SCADA schematics using sensitive
keywords, and staged them in archives for exfiltration.
labels:
- hunt
- attack.t1195
- attack.t1190
- attack.t1083
- attack.t1560
- attack.t1041
name: Integrator Supply Chain Compromise and SCADA Data Exfiltration
parameters:
integrator_ips:
default: []
description: Known IP ranges of third-party integrators; if empty, the hunt checks
all external successes.
from:
kind: manual
observed: '2026-09-23'
ref: customer-inventory
type: list[ip]
lookback_days:
default: '14'
description: Days of history to examine.
from:
kind: manual
observed: '2026-09-23'
ref: standard-baseline
type: number
scada_keywords:
default:
- scada
- customer
- customers
- schematic
- plc
- diagram
description: Keywords potentially used in filenames during the discovery phase.
from:
kind: article
observed: '2026-09-23'
ref: cisa-advisory-integrators
type: list[string]
scope_hosts:
default: []
description: Hosts identified in the scoping query to narrow the second-stage
search.
from:
kind: manual
observed: '2026-09-23'
ref: analyst-scoping
type: list[host]
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://www.cisa.gov/resources-tools/resources/considerations-critical-infrastructure-operators-working-third-party-ics-integrators
gates:
- dry-run
- lint
- critic
model: hb_google/gemini-3-flash-preview
rationale: Focus on engineering workstations, jump hosts, and jump servers that are
accessible to third-party integrators. Use the internet-exposed inventory to identify
potential entry points.
references:
- name: 'CISA Advisory: Considerations for Critical Infrastructure Operators Working
With Third-Party ICS Integrators'
url: https://www.cisa.gov/resources-tools/resources/considerations-critical-infrastructure-operators-working-third-party-ics-integrators
related:
- hunt: lateral-movement-via-engineering-tools
reason: Once an integrator's beachhead is established, lateral movement using legitimate
engineering tools is the next likely step.
relation: follows
scenario:
stages:
- name: Supply Chain or Exploit Access
observables:
- Remote access connections from integrator networks
- Exploitation of public-facing applications
- Industrial automation solution company network access
slug: initial-access-integrator-pivot
tactic: initial-access
techniques:
- T1195
- T1190
- name: File and Keyword Discovery
observables:
- 'Search terms: ''customers'''
- 'Search terms: ''SCADA'''
- Access to ICS device details and schematics
slug: discovery-sensitive-keywords
tactic: discovery
techniques:
- T1083
- name: Data Staging in ZIP Archives
observables:
- Creation of nine .zip files
- Bundling of approximately 800 files
- Archive names containing SCADA or customer information
slug: collection-archive-staging
tactic: collection
techniques:
- T1560
- name: Exfiltration over C2
observables:
- Outbound transfer of ZIP archives
- Communication with external infrastructure
slug: exfiltration-c2-channel
tactic: exfiltration
techniques:
- T1041
summary: Foreign cyber actors compromised a U.S. industrial automation solutions
provider to gain access to downstream critical infrastructure customer data. The
actors searched for SCADA configurations and schematics, bundled them into ZIP
archives, and exfiltrated the data to enable future disruptive attacks against
ICS environments.
severity: high
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
network:
category: network
name: Network telemetry
telemetry:
- network
tlp: clear
type: investigation
---
# Integrator Supply Chain Compromise and SCADA Data Exfiltration
This hunt follows a phased flow to detect the end-to-end attack chain reported by FBI and CISA. The hunt first identifies internet-exposed assets and triages early access markers like logins from integrator-owned IPs or anomalous inbound traffic. If the hunt identifies an early beachhead, it fans out to look for follow-on discovery behavior like keyword searches for SCADA and customers, rare data staging in .zip archives, and significant outbound traffic spikes. This mirrors the activity where an adversary compromised a U.S. industrial automation company to reach power and transportation utility customers. One agent evaluates the early signs of breach, while a second agent weighs the complete chain to confirm exfiltration. Finally, an analyst reviews the findings to isolate the host and revoke credentials.
## exposed-asset-inventory
<!-- Identify internet-exposed assets -->
Find the assets that are externally reachable and serve as the most likely pivot points from an integrator.
```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hostnames or IPs with internet exposure. Silence means no assets
are currently cataloged as exposed.
reads:
- domain_or_ip
- product
- asset_type
- port
silence: not_evidence_of_absence
source: hb_exposed_assets
verified: dry-run
verified_at: '2026-09-24'
~~~
SELECT domain_or_ip, product, asset_type, port FROM hb_exposed_assets WHERE asset_type = 'service'
```
## early-access-fan-out
<!-- Triage early access markers -->
parallel:
- → auth-logins-from-integrators
- → external-inbound-connections
join: → early-access-triage
## auth-logins-from-integrators
<!-- Authentication from integrator sources -->
Check for successful logins from the integrator's network or external sources into the estate.
```sqlite target=identity role=enrichment params=(integrator_ips=integrator_ips, lookback_days=lookback_days)
~~~yaml
expected: Rows mapping users and IPs to successful logins. If integrator_ips is empty,
any external-to-internal successful auth is returned.
reads:
- actor_user_name
- src_endpoint_ip
- dst_endpoint_name
- time
- status_id
silence: not_evidence_of_absence
source: hb_auth_signin
verified: dry-run
verified_at: '2026-09-24'
~~~
SELECT actor_user_name, src_endpoint_ip, dst_endpoint_name, time FROM hb_auth_signin WHERE status_id = 1 AND ('{{integrator_ips}}' = '' OR instr(',' || '{{integrator_ips}}' || ',', ',' || src_endpoint_ip || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```
## external-inbound-connections
<!-- Anomalous inbound network sessions -->
Identify inbound log sessions from external IPs that might signify exploitation of a public application.
```sqlite target=network role=enrichment params=(lookback_days=lookback_days)
~~~yaml
expected: Evidence of external IP addresses establishing connections to internal endpoints.
reads:
- device_hostname
- src_endpoint_ip
- dst_endpoint_port
- time
- direction
- state_kind
silence: not_evidence_of_absence
source: hb_network_connection
verified: dry-run
verified_at: '2026-09-24'
~~~
SELECT device_hostname, src_endpoint_ip, dst_endpoint_port, time FROM hb_network_connection WHERE direction = 'inbound' AND state_kind = 'log' AND time >= datetime('now', '-{{lookback_days}} days')
```
## early-access-triage
<!-- Triaging early access -->
```agent target=hunter
cite: required
context:
- exposed-asset-inventory
- auth-logins-from-integrators
- external-inbound-connections
max_iterations: 3
objective: Determine if any host in the scope has received suspicious logins or network
traffic from external sources.
success_criteria: A verdict citing specific rows for any host with external login
success or anomalous inbound traffic.
tools:
- endpoint
- identity
- network
```
## follow-on-fan-out
<!-- Search for follow-on behavior -->
parallel:
- → discovery-by-keywords
- → archive-creation-prevalence
- → exfiltration-traffic-peaks
join: → follow-on-triage
## discovery-by-keywords
<!-- Sensitive keyword file access -->
Detect an actor searching for SCADA schematics or customer data as mentioned in the advisory.
```sqlite target=endpoint role=detection-candidate params=(scope_hosts=scope_hosts, scada_keywords=scada_keywords, lookback_days=lookback_days)
~~~yaml
expected: A process accessing or creating files with keywords like 'SCADA' or 'customer'.
None means those exact terms were not observed in filenames.
reads:
- device_hostname
- file_name
- file_path
- process_name
- time
silence: not_evidence_of_absence
source: hb_file_activity
verified: dry-run
verified_at: '2026-09-24'
~~~
SELECT device_hostname, file_name, file_path, process_name, time FROM hb_file_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND instr(',' || '{{scada_keywords}}' || ',', ',' || LOWER(file_name) || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days')
```
## archive-creation-prevalence
<!-- Rare archive creation prevalence -->
Find the staging of multiple files into archives, which is rare across the fleet.
```sqlite target=endpoint role=baseline params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
baseline:
compare: first_seen
window: '{{lookback_days}}d'
expected: A host where a process creates multiple archives. Baseline analysis highlights
those that are rare.
prevalence:
by: device_hostname
key:
- process_name
rare_below: 3
reads:
- device_hostname
- process_name
- file_path
- activity_id
- time
silence: not_evidence_of_absence
source: hb_file_activity
verified: dry-run
verified_at: '2026-09-24'
~~~
SELECT device_hostname, process_name, COUNT(DISTINCT file_path) AS archive_count, MIN(time) AS first_seen FROM hb_file_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND (LOWER(file_path) LIKE '%.zip' OR LOWER(file_path) LIKE '%.7z') AND activity_id = 1 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name HAVING archive_count > 1
```
## exfiltration-traffic-peaks
<!-- Exfiltration traffic peaks -->
Identify significant outbound data transfers that match the expected staging size.
```sqlite target=network role=enrichment params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: A host sending more than 5MB of data to an external IP. Silence proofs absence
of large transfers to single destinations.
reads:
- device_hostname
- dst_endpoint_ip
- traffic_bytes
- direction
- state_kind
- time
silence: evidence_of_absence
source: hb_network_connection
verified: dry-run
verified_at: '2026-09-24'
~~~
SELECT device_hostname, dst_endpoint_ip, SUM(traffic_bytes) AS total_bytes FROM hb_network_connection WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND direction = 'outbound' AND state_kind = 'log' AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, dst_endpoint_ip HAVING total_bytes > 5000000
```
## follow-on-triage
<!-- Full chain verdict -->
```agent target=hunter
cite: required
context:
- early-access-triage
- discovery-by-keywords
- archive-creation-prevalence
- exfiltration-traffic-peaks
max_iterations: 5
objective: Decide if the observed behavior on a host constitutes a successful exfiltration
of sensitive industrial data following an integrator pivot.
success_criteria: A per-host verdict citing the beachhead markers followed by keyword-specific
file access or rare staging behavior.
tools:
- endpoint
- identity
- network
```
## incident-decision
<!-- Route on full verdict -->
if~: "the follow-on-triage verdict identifies a host with both early-access markers and subsequent discovery or staging behavior" (confidence: high, judge=hunter)
then: → contain-host
indeterminate: → analyst-review
unavailable: → analyst-review (blind_spot: limited-endpoint-visibility)
else: → close-out
## contain-host
<!-- Contain suspected host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the endpoint and revoke any associated integrator credentials.
```
→ analyst-review
## analyst-review
<!-- Analyst final review -->
```manual target=analyst
Review the file paths and process command lines for the keywords; confirm the destination of the exfiltration traffic.
```
→ end
## close-out
<!-- Close out hunt -->
```manual target=analyst
Document that the integrator pivot and SCADA exfiltration scenario was not observed for the given scope and window.
```
→ 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, critic, then reviewed by a person.