Interactive Shells and Data Collection (CL-UNK-1211)
An adversary is using in-memory reverse shells to conduct interactive discovery and exfiltrate government mailboxes, likely use AI-assisted scripting patterns for efficiency.
Based on research by Unit 42 2026-10-17 11 steps · 3 queries T1041 T1059 T1071
Brief
Why this hunt
Unit 42 recently detailed a campaign they call AI-Powered Espionage Campaign Targets Government Linux Infrastructure. The threat actor uses AI-assisted scripting to speed up their discovery and data collection phases. This hunt targets the active intrusion stage where the adversary establishes interactive control and gathers mail data.
How the Hunt Flows
The first phase looks for the characteristic behavioral patterns of in-memory reverse shells. The query examines hb_process_activity for command lines involving mkfifo paired with nc, /dev/tcp/ redirects, or specific Python subprocess calls. This lead provides the entry point for the investigation.
If the lead returns suspicious activity, the hunt fans out into a parallel corroboration phase. One branch checks for network connections to known C2 IP addresses from the hb_network_connection surface. This confirms if the shell is communicating with the infrastructure identified in the report.
The second parallel branch stacks directory enumeration and compression commands involving mail storage. By looking for zip, tar, or find commands in /var/qmail/ or /maildir/ paths, the hunt identifies data collection. It filters frequent administrative backups to highlight rare, targeted exfiltration.
The final stage weighs the evidence from all branches. An analyst or an automated agent triages the findings to confirm an active intrusion. If the shell, network traffic, and collection patterns align, the hunt triggers host isolation.
What this hunt cannot see
This hunt has specific blind spots. If an adversary executes a bash redirect inside a complex script using eval or within a pre-existing shell session without spawning a new process, the command line may not appear in process logs. Additionally, the hunt identifies network connections to C2 IPs but cannot inspect encrypted WebSocket traffic. While it sees the destination, it cannot confirm the specific protocol or URI path without a decrypting proxy.
In this series
Steps
-
Suspicious reverse shell patterns
Query · detection candidateIdentify the characteristic behavioral patterns of in-memory reverse shells using pipes, redirects, or scripted sockets.
reads hb_process_activitysqlSELECT device_hostname, user_name, process_cmd_line, time FROM hb_process_activity WHERE ((LOWER(process_cmd_line) LIKE '%mkfifo%' AND LOWER(process_cmd_line) LIKE '%nc %') OR (LOWER(process_cmd_line) LIKE '%/dev/tcp/%') OR (LOWER(process_cmd_line) LIKE '%socket.socket%' AND LOWER(process_cmd_line) LIKE '%subprocess.call%')) AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Rows containing shell commands that redirect I/O to network sockets. Silence indicates no shell redirection was captured in the process logs during the window.
-
Assess lead validity
Agent triageDetermine if the identified reverse shell patterns are likely malicious or part of legitimate administrative activity.
-
Gate on reverse shell activity
DecisionStop the hunt if no suspicious shells are found to conserve resources.
-
Network connections to C2 IPs
Query · enrichmentVerify if the hosts with suspicious shells are communicating with the reported C2 infrastructure.
reads hb_network_connectionsqlSELECT device_hostname, process_name, dst_endpoint_ip, dst_endpoint_port, time FROM hb_network_connection WHERE instr(',' || '{{c2_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Outbound connections to 104.194.158.65. Silence does not rule out infection if the adversary rotated IPs.
-
Rare mailbox access and compression
Query · baselineStack-count directory enumeration and compression commands involving mail storage to identify data collection while filtering common administrative noise.
reads hb_process_activitysqlSELECT LOWER(process_cmd_line) AS cmd, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE (LOWER(process_cmd_line) LIKE '%/var/qmail/%' OR LOWER(process_cmd_line) LIKE '%/maildir/%' OR LOWER(process_cmd_line) LIKE '%/cur/%') AND (LOWER(process_cmd_line) LIKE '%zip %' OR LOWER(process_cmd_line) LIKE '%tar %' OR LOWER(process_cmd_line) LIKE '%find %') AND LOWER(process_name) NOT LIKE '%backup%' AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY 1 HAVING host_count <= 3What a hit looks like. A rare command string zipping a mail directory on one or two hosts. Genuine backup processes should be frequent across the fleet.
-
Combined evidence triage
Agent triageWeigh the shell activity, C2 hits, and data collection patterns to reach a final verdict.
-
Route based on confirmed intrusion
DecisionIsolate confirmed malicious hosts or route suspicious findings to manual review.
-
Isolate confirmed host
Response actionContain the breach by isolating the host from the network while maintaining investigation access.
-
Analyst manual review
Analyst taskValidate findings that were not automatically isolated and prepare a report.
-
Hunt close-out
Analyst taskFinalize the hunt run and record gaps.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| In-Memory Reverse Shells T1059 |
Yes | lead-reverse-shells |
| WebSocket Command and Control T1071 |
Yes | c2-network-hits |
| Mailbox and Database Collection T1041 |
Yes | mailbox-access-baseline |
| Web Shell Deployment T1505.003 |
Out of scope | Handled by the preceding hunt in this series. |
| PHP Configuration Tampering T1505.003 |
Out of scope | Handled by the preceding hunt in this series. |
| Sudo Command Hijacking T1059 |
Out of scope | Handled by the preceding hunt in this series. |
| SysGoRAT Backdoor Execution T1059 |
Out of scope | Handled by the preceding hunt in this series. |
Blind spots
- Needs command-line auditing or script block logging on Linux. If the bash redirect is executed via an eval or inside a pre-existing shell without a new process launch, the command line might not be visible in hb_process_activity. It would answer whether the redirect pattern bash -i >& /dev/tcp/ was executed inside a complex script.
- Needs hb_http_activity with decrypted WebSocket headers. WebSocket traffic (wss://) is encrypted; hb_network_connection sees only the IP and port, preventing confirmation of the WebSocket protocol or URI path without a decrypting proxy. It would answer whether the WebSocket traffic was for SysGoRAT or a benign service.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
c2_ips | list[ip] | 104.194.158.65 | Known C2 IP addresses from the CL-UNK-1211 report. |
lookback_days | number | 14 | Days of history to examine. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Network telemetry | network | network |
Source
---
analysis: A simple rule for 'nc' or 'bash -i' is often too noisy for developer-heavy
Linux environments. This hunt pivots from the initial behavioral lead to verify
C2 traffic and then stack-counts the specific data collection patterns (mailbox
zipping) that define this intrusion cluster, using three surfaces to confirm a breach.
blind_spots:
- id: shell-visibility-gap
question: whether the redirect pattern bash -i >& /dev/tcp/ was executed inside
a complex script
requires: command-line auditing or script block logging on Linux
risk: If the bash redirect is executed via an eval or inside a pre-existing shell
without a new process launch, the command line might not be visible in hb_process_activity.
stage: reverse-shell-activity
- id: network-visibility-gap
question: whether the WebSocket traffic was for SysGoRAT or a benign service
requires: hb_http_activity with decrypted WebSocket headers
risk: WebSocket traffic (wss://) is encrypted; hb_network_connection sees only the
IP and port, preventing confirmation of the WebSocket protocol or URI path without
a decrypting proxy.
stage: c2-communication
coverage:
- stage: reverse-shell-activity
status: covered
steps:
- lead-reverse-shells
- stage: c2-communication
status: covered
steps:
- c2-network-hits
- stage: data-collection-exfiltration
status: covered
steps:
- mailbox-access-baseline
- reason: Handled by the preceding hunt in this series.
stage: web-shell-deployment
status: out_of_scope
- reason: Handled by the preceding hunt in this series.
stage: php-persistence-tampering
status: out_of_scope
- reason: Handled by the preceding hunt in this series.
stage: credential-harvesting-sudo
status: out_of_scope
- reason: Handled by the preceding hunt in this series.
stage: sysgorat-execution
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: The exfiltration of government mailboxes and databases represents
a critical loss of sensitive data; a negative result for these collection patterns
over the mail infrastructure is a high-value signal for national security.
methodology: model-assisted
trigger: intel-report
hypothesis: An adversary is using in-memory reverse shells to conduct interactive
discovery and exfiltrate government mailboxes, likely use AI-assisted scripting
patterns for efficiency.
labels:
- hunt
- attack.t1059
- attack.t1071
- attack.t1041
- collection
- command and control
- credential access
- execution
- persistence
name: Interactive Shells and Data Collection (CL-UNK-1211)
parameters:
c2_ips:
default:
- 104.194.158.65
description: Known C2 IP addresses from the CL-UNK-1211 report.
from:
kind: article
observed: '2026-10-15'
ref: unit42-ai-espionage-2026
type: list[ip]
lookback_days:
default: '14'
description: Days of history to examine.
type: number
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://unit42.paloaltonetworks.com/ai-campaign-targets-linux-infrastructure/
gates:
- dry-run
- lint
model: hb_google/gemini-3-flash-preview
rationale: Focus the hunt on Linux-based mail servers (qmail, postfix) and database
servers, as these are the primary targets for the collection techniques described
in the CL-UNK-1211 report.
references:
- name: "Unit 42 \u2014 AI-Powered Espionage Campaign Targets Government Linux Infrastructure"
url: https://unit42.paloaltonetworks.com/ai-campaign-targets-linux-infrastructure/
related:
- hunt: cl-unk-1211-initial-access-and-persistence
reason: The initial web shell deployment and credential harvesting phase are handled
in a separate hunt focused on web server persistence.
relation: precedes
- hunt: linux-persistence-credential-hijacking
relation: follows
scenario:
stages:
- name: Web Shell Deployment
observables:
- /usr/lib/php/plesk_sys_driver.php
- POST requests to PHP files via php-fpm parent process
- search_social.php
slug: web-shell-deployment
tactic: persistence
techniques:
- T1505.003
- name: PHP Configuration Tampering
observables:
- Modification of auto_prepend_file in /etc/php/
- Modification of auto_prepend_file in /opt/plesk/php/
slug: php-persistence-tampering
tactic: persistence
techniques:
- T1505.003
- name: Sudo Command Hijacking
observables:
- Modification of .bashrc with sudo aliases
- Solarwinds.StatusLog.txt
- Commands searching for SMTP or database passwords in config files
slug: credential-harvesting-sudo
tactic: credential-access
techniques:
- T1059
- name: SysGoRAT Backdoor Execution
observables:
- sys-control-client
- pip2.7
- ea_install
- ./semanage
- Go-based multi-platform RAT
slug: sysgorat-execution
tactic: execution
techniques:
- T1059
- name: In-Memory Reverse Shells
observables:
- mkfifo /tmp/f; cat /tmp/f | bash -i 2>&1 | nc
- bash -i >& /dev/tcp/
- python3 -c "import socket,subprocess,os; s=socket.socket(...)"
slug: reverse-shell-activity
tactic: execution
techniques:
- T1059
- name: WebSocket Command and Control
observables:
- wss://<addr>/ws
- 104.194.158.65:443
- proxy_connect command via RAT
slug: c2-communication
tactic: command-and-control
techniques:
- T1071
- name: Mailbox and Database Collection
observables:
- Enumeration of /var/qmail/mailnames/
- zip_mails.sh
- Iteration through Maildir/cur/ directories
slug: data-collection-exfiltration
tactic: collection
techniques:
- T1041
summary: CL-UNK-1211 is an AI-assisted campaign targeting government Linux infrastructure
to exfiltrate mailboxes and sensitive databases. The attackers utilize custom
Go-based backdoors (SysGoRAT), extensive web shell deployments, and creative credential
theft such as hijacking the sudo command through .bashrc modifications.
series:
index: 2
slug: ai-powered-espionage-campaign-targets-government-linux-infrastructure
title: AI-Powered Espionage Campaign Targets Government Linux Infrastructure
total: 2
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
network:
category: network
name: Network telemetry
telemetry:
- network
tlp: clear
type: investigation
---
# Interactive Shells and Data Collection (CL-UNK-1211)
This hunt focuses on the active intrusion phase of the CL-UNK-1211 campaign. It identifies behavioral indicators of interactive reverse shells (Netcat, Bash redirects, and Python subprocesses) which the attacker uses to enumerate and compress mailbox data for exfiltration. The hunt uses a gated flow, first identifying the characteristic shell patterns before fanning out to check for known C2 traffic and unusual mailbox access across the Linux estate.
## lead-reverse-shells
<!-- Suspicious reverse shell patterns -->
Identify the characteristic behavioral patterns of in-memory reverse shells using pipes, redirects, or scripted sockets.
```sqlite target=endpoint role=detection-candidate params=(lookback_days=lookback_days)
~~~yaml
expected: Rows containing shell commands that redirect I/O to network sockets. Silence
indicates no shell redirection was captured in the process logs during the window.
reads:
- device_hostname
- process_cmd_line
- time
- user_name
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-10-17'
~~~
SELECT device_hostname, user_name, process_cmd_line, time FROM hb_process_activity WHERE ((LOWER(process_cmd_line) LIKE '%mkfifo%' AND LOWER(process_cmd_line) LIKE '%nc %') OR (LOWER(process_cmd_line) LIKE '%/dev/tcp/%') OR (LOWER(process_cmd_line) LIKE '%socket.socket%' AND LOWER(process_cmd_line) LIKE '%subprocess.call%')) AND time >= datetime('now', '-{{lookback_days}} days')
```
## lead-assessment
<!-- Assess lead validity -->
```agent target=hunter
cite: required
context:
- lead-reverse-shells
max_iterations: 3
objective: Decide if the reverse shell patterns in lead-reverse-shells require further
investigation based on the context of the user and host.
success_criteria: A verdict of malicious | suspicious | benign for the reverse shell
patterns found.
tools:
- endpoint
- network
```
## gate-on-lead
<!-- Gate on reverse shell activity -->
if~: "the lead-assessment verdict is malicious or suspicious for at least one host" (confidence: high, judge=hunter)
then: → parallel-corroboration
indeterminate: → manual-review
unavailable: → manual-review (blind_spot: shell-visibility-gap)
else: → close-out
## parallel-corroboration
<!-- Corroborate with network and collection logs -->
parallel:
- → c2-network-hits
- → mailbox-access-baseline
join: → final-triage
## c2-network-hits
<!-- Network connections to C2 IPs -->
Verify if the hosts with suspicious shells are communicating with the reported C2 infrastructure.
```sqlite target=network role=enrichment params=(lookback_days=lookback_days, c2_ips=c2_ips)
~~~yaml
expected: Outbound connections to 104.194.158.65. Silence does not rule out infection
if the adversary rotated IPs.
reads:
- device_hostname
- dst_endpoint_ip
- dst_endpoint_port
- process_name
- time
silence: not_evidence_of_absence
source: hb_network_connection
verified: dry-run
verified_at: '2026-10-17'
~~~
SELECT device_hostname, process_name, dst_endpoint_ip, dst_endpoint_port, time FROM hb_network_connection WHERE instr(',' || '{{c2_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days')
```
## mailbox-access-baseline
<!-- Rare mailbox access and compression -->
Stack-count directory enumeration and compression commands involving mail storage to identify data collection while filtering common administrative noise.
```sqlite target=endpoint role=baseline params=(lookback_days=lookback_days)
~~~yaml
baseline:
compare: first_seen
window: '{{lookback_days}}d'
expected: A rare command string zipping a mail directory on one or two hosts. Genuine
backup processes should be frequent across the fleet.
prevalence:
by: device_hostname
key:
- cmd
rare_below: 3
reads:
- device_hostname
- process_cmd_line
- process_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-10-17'
~~~
SELECT LOWER(process_cmd_line) AS cmd, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE (LOWER(process_cmd_line) LIKE '%/var/qmail/%' OR LOWER(process_cmd_line) LIKE '%/maildir/%' OR LOWER(process_cmd_line) LIKE '%/cur/%') AND (LOWER(process_cmd_line) LIKE '%zip %' OR LOWER(process_cmd_line) LIKE '%tar %' OR LOWER(process_cmd_line) LIKE '%find %') AND LOWER(process_name) NOT LIKE '%backup%' AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY 1 HAVING host_count <= 3
```
## final-triage
<!-- Combined evidence triage -->
```agent target=hunter
cite: required
context:
- lead-assessment
- c2-network-hits
- mailbox-access-baseline
max_iterations: 6
objective: Determine if the evidence across lead-reverse-shells, c2-network-hits,
and mailbox-access-baseline confirms an active intrusion on the target hosts.
success_criteria: A combined verdict on whether the initial shell activity and follow-on
collection constitute a confirmed intrusion.
tools:
- endpoint
- network
```
## route-on-verdict
<!-- Route based on confirmed intrusion -->
if~: "the final-triage verdict is malicious for at least one host" (confidence: high, judge=hunter)
then: → isolate-endpoint
indeterminate: → manual-review
unavailable: → manual-review (blind_spot: network-visibility-gap)
else: → manual-review
## isolate-endpoint
<!-- Isolate confirmed host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host and preserve process memory to capture the in-memory shell scripts and the SysGoRAT binary.
```
→ manual-review
## manual-review
<!-- Analyst manual review -->
```manual target=analyst
Review the shell commands and network hits; determine if the mailbox collection represents a breach of sensitive data and notify the relevant government mailbox owners.
```
→ close-out
## close-out
<!-- Hunt close-out -->
```manual target=analyst
Document the findings and update the detection rule for reverse shells based on any tuning notes identified.
```
→ 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.