VERDANTBAMBOO Edge Appliance Post-Exploitation
An adversary compromises an edge appliance, uses an inadvertent sudo configuration to escalate to root, and creates persistence via cron to tunnel traffic through DNS-over-HTTPS.
Based on research by Volexity 2026-09-20 12 steps · 5 queries T1053.003 T1059.004 T1071.001 T1078 T1090.003 T1548.003
Brief
Why this hunt
Edge appliances are attractive targets for adversaries like VerdantBamboo because they often lack standard endpoint security. This hunt is based on research by Volexity — VERDANTBAMBOO: Just Another BRICKSTORM in the Firewall (https://www.volexity.com/blog/2026/06/04/verdantbamboo-just-another-brickstorm-in-the-firewall/). The actor uses these devices to proxy traffic and gain a persistent foothold within the network.
How the hunt flows
The first step scopes the environment to identify relevant appliances. It searches for hosts running Egnyte Storage Sync, pfSense, or Synology services, and looks for the specific egnyteservice account. This ensures subsequent queries focus on the high-risk surfaces where the actor operates.
The hunt then searches for early indicators of compromise in parallel. It checks for the abuse of sudo and tee to write to protected system directories, which is the specific method the adversary uses for privilege escalation on these devices. Simultaneously, it stacks process executions from system paths like /usr/sbin/ and /usr/local/libexec/ to find rare binaries that may be actor-deployed implants.
Next, the hunt looks for evidence of persistence and command-and-control. It examines cron job definitions for commands pointing to user-controlled or temporary directories. It also identifies network connections to Google Public DNS over port 443, which matches the DNS-over-HTTPS (DoH) proxying pattern used by the BRICKSTORM malware. This network check is restricted to the appliances identified in the scoping phase to keep results focused.
Finally, an analyst triages the collected evidence. By correlating the privilege escalation, the presence of rare binaries, and the network tunneling on the same host, the analyst can confirm if an appliance is compromised. This contextual join provides higher confidence than a single detection rule.
What the hunt cannot see
The hunt cannot identify compromised appliances that do not report telemetry to an EDR or central log source. If an appliance is unmanaged or legacy, it may host an implant invisibly. Additionally, the DNS-over-HTTPS check identifies traffic to Google DNS but cannot verify the specific C2 domain without TLS decryption or proxy URI logs.
In this series
Steps
-
Identify edge appliances and appliance users
Query · scopingIdentify Linux-based appliances and default service accounts that are targets for VerdantBamboo.
reads hb_process_activitysqlSELECT DISTINCT device_hostname FROM hb_process_activity WHERE (LOWER(process_path) LIKE '%egnyte%' OR LOWER(process_path) LIKE '%pfsense%' OR LOWER(process_path) LIKE '%synology%' OR LOWER(user_name) = 'egnyteservice') AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. A list of hostnames belonging to network or storage appliances. Silence suggests these devices are not reporting telemetry.
-
Sudo tee abuse for system path writes
Query · detection candidateFind instances where sudo tee was used to write to protected directories, matching the Egnyte appliance LPE technique.
reads hb_process_activitysqlSELECT device_hostname, process_cmd_line, user_name, time FROM hb_process_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(process_cmd_line) LIKE '%sudo %' AND LOWER(process_cmd_line) LIKE '%tee %' AND (LOWER(process_cmd_line) LIKE '%/etc/%' OR LOWER(process_cmd_line) LIKE '%/usr/%' OR LOWER(process_cmd_line) LIKE '%/bin/%') AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Command lines where an unprivileged user writes to system configuration or binary paths. Silence proof of absence for this specific command pattern.
-
Rare processes in appliance system directories
Query · baselineStack-count processes running from system directories to identify one-off implants.
reads hb_process_activitysqlSELECT LOWER(process_path) AS path, COUNT(DISTINCT device_hostname) AS hosts, COUNT(*) AS runs, MIN(time) AS first_seen FROM hb_process_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND (LOWER(process_path) LIKE '/usr/sbin/%' OR LOWER(process_path) LIKE '/usr/local/libexec/%' OR LOWER(process_path) LIKE '/home/egnyteservice/%') AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY path HAVING hosts <= 2What a hit looks like. Binaries running from protected system paths that appear on very few hosts. Silence is evidence of absence for these specific paths.
-
Triage early compromise evidence
Agent triageEvaluate if sudo abuse and rare binary activity on the same host indicate a compromised edge appliance.
-
Scheduled cron persistence for implants
Query · enrichmentFind cron jobs pointing to world-writable or user-controlled paths identified in earlier stages.
reads hb_scheduled_jobsqlSELECT device_hostname, job_cmd_line, job_definition_path, time FROM hb_scheduled_job WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND (LOWER(job_cmd_line) LIKE '/home/%' OR LOWER(job_cmd_line) LIKE '/tmp/%' OR LOWER(job_cmd_line) LIKE '/var/tmp/%' OR LOWER(job_cmd_line) LIKE '/usr/local/bin/egnyte/%') AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Cron jobs defined in system paths that execute user-mode scripts or binaries in non-standard directories.
-
DNS-over-HTTPS to Google Public DNS
Query · enrichmentDetect network connections on port 443 to Google Public DNS, matching the BRICKSTORM DoH proxying pattern, limited to scoped appliances.
reads hb_network_connectionsqlSELECT device_hostname, process_name, dst_endpoint_ip, dst_endpoint_port, time FROM hb_network_connection WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND instr(',' || '{{google_dns_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0 AND dst_endpoint_port = 443 AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Any scoped appliance initiating HTTPS traffic directly to Google DNS IPs. Silence suggests this specific C2 method is not in use.
-
Follow-on compromise analysis
Agent triageAssess the full attack chain including persistence and C2 to provide a definitive verdict.
-
Route on verdict
DecisionRoute the hunt based on the agent's full-chain analysis.
-
Isolate compromised appliance
Response actionPrevent further C2 proxying or lateral movement by isolating the identified appliance.
-
Analyst remediation and forensics
Analyst taskManually verify the findings and search for lateral movement aftermath.
-
Final close out
Analyst taskRecord findings and determine if this hunt should be recurring.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| Local Privilege Escalation via Sudo Tee T1059 |
Yes | sudo-tee-write |
| Persistence via Scheduled Cron Jobs T1059 |
Yes | cron-persistence-check |
| Deployment of BRICKSTORM and AGENTPSD T1059 · T1505.003 |
Yes | rare-appliance-binaries |
| C2 and Proxying via DoH and Cloudflare T1071 · T1090.003 |
Yes | doh-c2-check |
| Access via Stolen Appliance Credentials T1078 · T1133 |
Out of scope | Belongs to another part of the 'VERDANTBAMBOO: Just Another BRICKSTORM in the Firewall' series. |
| Lateral Movement to Synology NAS T1078 · T1133 |
Out of scope | Belongs to another part of the 'VERDANTBAMBOO: Just Another BRICKSTORM in the Firewall' series. |
Blind spots
- Needs endpoint agent coverage on third-party appliances. An unmanaged or legacy appliance could host the BRICKSTORM proxy without any behavioral telemetry reaching our surfaces. It would answer whether a compromised appliance exists if it does not report to our EDR.
- Needs TLS inspection or proxy logs with URI visibility. We can identify traffic to Google DNS but cannot verify the specific C2 domain without decrypting the HTTPS session, potentially leading to false positives if DoH is used for legitimate purposes. It would answer what domain is being resolved via DNS-over-HTTPS.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
google_dns_ips | list[ip] | 8.8.8.8, 8.8.4.4 | Google Public DNS IPs used for DNS-over-HTTPS tunneling. |
lookback_days | number | 14 | Days of history to examine. |
scope_hosts | list[host] | — | List of specific appliances to hunt; leave empty to scan the full estate. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Network telemetry | network | network |
Source
---
analysis: This hunt contextually joins privilege escalation, rare binary deployment,
and the specific use of DoH to confirm the VerdantBamboo attack chain. A single
detection rule on sudo tee or network connections to 8.8.8.8 would generate excessive
noise without the multi-surface correlation used here.
blind_spots:
- id: no-appliance-telemetry
question: whether a compromised appliance exists if it does not report to our EDR
requires: endpoint agent coverage on third-party appliances
risk: An unmanaged or legacy appliance could host the BRICKSTORM proxy without any
behavioral telemetry reaching our surfaces.
- id: encrypted-doh-traffic
question: what domain is being resolved via DNS-over-HTTPS
requires: TLS inspection or proxy logs with URI visibility
risk: We can identify traffic to Google DNS but cannot verify the specific C2 domain
without decrypting the HTTPS session, potentially leading to false positives if
DoH is used for legitimate purposes.
stage: c2-proxying-via-doh-and-cloudflare
coverage:
- stage: local-privilege-escalation-sudo-tee
status: covered
steps:
- sudo-tee-write
- stage: persistence-via-scheduled-cron
status: covered
steps:
- cron-persistence-check
- stage: malware-deployment-brickstorm-agentpsd
status: covered
steps:
- rare-appliance-binaries
- stage: c2-proxying-via-doh-and-cloudflare
status: covered
steps:
- doh-c2-check
- reason: 'Belongs to another part of the ''VERDANTBAMBOO: Just Another BRICKSTORM
in the Firewall'' series.'
stage: initial-access-stolen-appliance-credentials
status: out_of_scope
- reason: 'Belongs to another part of the ''VERDANTBAMBOO: Just Another BRICKSTORM
in the Firewall'' series.'
stage: lateral-movement-and-nas-compromise
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: Edge appliances are frequently targeted by state actors because they
often lack standard endpoint security and provide a stable pivot into corporate
networks and M365 environments.
methodology: model-assisted
trigger: intel-report
hypothesis: An adversary compromises an edge appliance, uses an inadvertent sudo configuration
to escalate to root, and creates persistence via cron to tunnel traffic through
DNS-over-HTTPS.
labels:
- hunt
- attack.t1059.004
- attack.t1078
- attack.t1548.003
- attack.t1053.003
- attack.t1071.001
- attack.t1090.003
name: VERDANTBAMBOO Edge Appliance Post-Exploitation
parameters:
google_dns_ips:
default:
- 8.8.8.8
- 8.8.4.4
description: Google Public DNS IPs used for DNS-over-HTTPS tunneling.
from:
kind: article
observed: '2026-06-04'
ref: https://www.volexity.com/blog/2026/06/04/verdantbamboo-just-another-brickstorm-in-the-firewall/
type: list[ip]
lookback_days:
default: '14'
description: Days of history to examine.
type: number
scope_hosts:
default: []
description: List of specific appliances to hunt; leave empty to scan the full
estate.
type: list[host]
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://www.volexity.com/blog/2026/06/04/verdantbamboo-just-another-brickstorm-in-the-firewall/
gates:
- dry-run
- lint
model: hb_google/gemini-3-flash-preview
rationale: Focus on Linux and BSD hosts identified as Storage Sync or pfSense appliances.
Use the user_name 'egnyteservice' as a high-fidelity anchor for Storage Sync virtual
machines.
references:
- name: "Volexity \u2014 VERDANTBAMBOO: Just Another BRICKSTORM in the Firewall"
url: https://www.volexity.com/blog/2026/06/04/verdantbamboo-just-another-brickstorm-in-the-firewall/
related:
- hunt: lateral-movement-and-nas-compromise
reason: This hunt identifies the initial appliance compromise; the follow-on lateral
movement to Synology NAS and ESXi is handled in the next hunt.
relation: follows
scenario:
stages:
- name: Access via Stolen Appliance Credentials
observables:
- egnyteservice
- SSH logins to Egnyte Storage Sync
- VPN IP address source for administrative logins
slug: initial-access-stolen-appliance-credentials
tactic: initial-access
techniques:
- T1078
- T1133
- name: Local Privilege Escalation via Sudo Tee
observables:
- sudo /usr/bin/tee
- /usr/local/bin/egnyte/rsync_data_migration.sh
- /usr/bin/systemctl restart networking
slug: local-privilege-escalation-sudo-tee
tactic: privilege-escalation
techniques:
- T1059
- name: Persistence via Scheduled Cron Jobs
observables:
- /etc/cron.d/ssync
- /home/egnyteservice/ssync.sh
- /etc/crontab entry for egnyte_host_monitor_client
- /etc/rc.d/cron modification on pfSense
slug: persistence-via-scheduled-cron
tactic: persistence
techniques:
- T1059
- name: Deployment of BRICKSTORM and AGENTPSD
observables:
- /usr/sbin/ (BRICKSTORM directory)
- /usr/local/bin/egnyte/egnyte_host_monitor_client
- /usr/local/libexec/ipsec/blacklist
slug: malware-deployment-brickstorm-agentpsd
tactic: execution
techniques:
- T1059
- T1505.003
- name: C2 and Proxying via DoH and Cloudflare
observables:
- 8.8.8.8:443
- TLS connections to Google Public DNS
- Cloudflare IP addresses
- M365 access via internal proxy traffic
slug: c2-proxying-via-doh-and-cloudflare
tactic: command-and-control
techniques:
- T1071
- T1090.003
- name: Lateral Movement to Synology NAS
observables:
- Synology NAS web interface admin logins
- PLENET malware deployment
- SSH enabled via web interface
slug: lateral-movement-and-nas-compromise
tactic: lateral-movement
techniques:
- T1078
- T1133
summary: VerdantBamboo compromised an MSP to obtain administrative credentials,
which were then used to breach edge appliances including Egnyte Storage Sync,
pfSense firewalls, and Synology NAS systems. The actor deployed BRICKSTORM and
AGENTPSD malware to establish persistence and create proxy tunnels into internal
networks and Microsoft 365 environments, effectively bypassing conditional access
policies by appearing as internal traffic.
series:
index: 1
slug: verdantbamboo-just-another-brickstorm-in-the-firewall
title: 'VERDANTBAMBOO: Just Another BRICKSTORM in the Firewall'
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
---
# VERDANTBAMBOO Edge Appliance Post-Exploitation
This hunt follows the tradecraft of VerdantBamboo on edge appliances like Egnyte Storage Sync and pfSense firewalls. The hunt identifies appliances and searches for high-fidelity privilege escalation via sudo tee abuse. It then corroborates these findings with rare binaries in system directories, persistence in cron configurations, and command-and-control traffic created via DNS-over-HTTPS (DoH) to Google Public DNS. This phased approach ensures that later network behaviors are evaluated in the context of early-stage compromise indicators.
## scoping-appliances
<!-- Identify edge appliances and appliance users -->
Identify Linux-based appliances and default service accounts that are targets for VerdantBamboo.
```sqlite target=endpoint role=scoping params=(lookback_days=lookback_days)
~~~yaml
expected: A list of hostnames belonging to network or storage appliances. Silence
suggests these devices are not reporting telemetry.
reads:
- device_hostname
- process_path
- time
- user_name
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT DISTINCT device_hostname FROM hb_process_activity WHERE (LOWER(process_path) LIKE '%egnyte%' OR LOWER(process_path) LIKE '%pfsense%' OR LOWER(process_path) LIKE '%synology%' OR LOWER(user_name) = 'egnyteservice') AND time >= datetime('now', '-{{lookback_days}} days')
```
## early-stage-investigation
<!-- Investigate early compromise indicators -->
parallel:
- → sudo-tee-write
- → rare-appliance-binaries
join: → agent-early-triage
## sudo-tee-write
<!-- Sudo tee abuse for system path writes -->
Find instances where sudo tee was used to write to protected directories, matching the Egnyte appliance LPE technique.
```sqlite target=endpoint role=detection-candidate params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
expected: Command lines where an unprivileged user writes to system configuration
or binary paths. Silence proof of absence for this specific command pattern.
reads:
- device_hostname
- process_cmd_line
- time
- user_name
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_cmd_line, user_name, time FROM hb_process_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(process_cmd_line) LIKE '%sudo %' AND LOWER(process_cmd_line) LIKE '%tee %' AND (LOWER(process_cmd_line) LIKE '%/etc/%' OR LOWER(process_cmd_line) LIKE '%/usr/%' OR LOWER(process_cmd_line) LIKE '%/bin/%') AND time >= datetime('now', '-{{lookback_days}} days')
```
## rare-appliance-binaries
<!-- Rare processes in appliance system directories -->
Stack-count processes running from system directories to identify one-off implants.
```sqlite target=endpoint role=baseline params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
baseline:
compare: first_seen
window: '{{lookback_days}}d'
expected: Binaries running from protected system paths that appear on very few hosts.
Silence is evidence of absence for these specific paths.
prevalence:
by: device_hostname
key:
- path
rare_below: 3
reads:
- device_hostname
- process_path
- time
silence: evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT LOWER(process_path) AS path, COUNT(DISTINCT device_hostname) AS hosts, COUNT(*) AS runs, MIN(time) AS first_seen FROM hb_process_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND (LOWER(process_path) LIKE '/usr/sbin/%' OR LOWER(process_path) LIKE '/usr/local/libexec/%' OR LOWER(process_path) LIKE '/home/egnyteservice/%') AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY path HAVING hosts <= 2
```
## agent-early-triage
<!-- Triage early compromise evidence -->
```agent target=hunter
cite: required
context:
- sudo-tee-write
- rare-appliance-binaries
max_iterations: 4
objective: Assess whether any appliance shows signs of both privilege escalation (sudo
tee) and rare binary execution in system directories.
success_criteria: A list of potentially compromised hosts citing process and command
line rows.
tools:
- endpoint
- network
```
## follow-on-investigation
<!-- Corroborate with persistence and C2 -->
parallel:
- → cron-persistence-check
- → doh-c2-check
join: → agent-follow-on-triage
## cron-persistence-check
<!-- Scheduled cron persistence for implants -->
Find cron jobs pointing to world-writable or user-controlled paths identified in earlier stages.
```sqlite target=endpoint role=enrichment params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
expected: Cron jobs defined in system paths that execute user-mode scripts or binaries
in non-standard directories.
reads:
- device_hostname
- job_cmd_line
- job_definition_path
- time
silence: not_evidence_of_absence
source: hb_scheduled_job
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, job_cmd_line, job_definition_path, time FROM hb_scheduled_job WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND (LOWER(job_cmd_line) LIKE '/home/%' OR LOWER(job_cmd_line) LIKE '/tmp/%' OR LOWER(job_cmd_line) LIKE '/var/tmp/%' OR LOWER(job_cmd_line) LIKE '/usr/local/bin/egnyte/%') AND time >= datetime('now', '-{{lookback_days}} days')
```
## doh-c2-check
<!-- DNS-over-HTTPS to Google Public DNS -->
Detect network connections on port 443 to Google Public DNS, matching the BRICKSTORM DoH proxying pattern, limited to scoped appliances.
```sqlite target=network role=enrichment params=(lookback_days=lookback_days, scope_hosts=scope_hosts, google_dns_ips=google_dns_ips)
~~~yaml
expected: Any scoped appliance initiating HTTPS traffic directly to Google DNS IPs.
Silence suggests this specific C2 method is not in use.
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-09-20'
~~~
SELECT device_hostname, process_name, dst_endpoint_ip, dst_endpoint_port, time FROM hb_network_connection WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND instr(',' || '{{google_dns_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0 AND dst_endpoint_port = 443 AND time >= datetime('now', '-{{lookback_days}} days')
```
## agent-follow-on-triage
<!-- Follow-on compromise analysis -->
```agent target=hunter
cite: required
context:
- agent-early-triage
- cron-persistence-check
- doh-c2-check
max_iterations: 6
objective: Identify hosts that exhibit the full chain of VerdantBamboo post-exploitation
activity by weighing early triage findings against cron persistence and DoH traffic.
success_criteria: A per-host verdict of malicious | suspicious | benign, citing rows
from all involved steps.
tools:
- endpoint
- network
```
## route-on-verdict
<!-- Route on verdict -->
if~: "The agent identifies at least one host as malicious or suspicious with evidence of the attack chain." (confidence: high, judge=hunter)
then: → isolate-host
indeterminate: → analyst-remediation
unavailable: → analyst-remediation (blind_spot: no-appliance-telemetry)
else: → final-close-out
## isolate-host
<!-- Isolate compromised appliance -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the compromised edge appliance and revoke any active administrative sessions. Collect logs from the appliance local file system before remediation.
```
→ analyst-remediation
## analyst-remediation
<!-- Analyst remediation and forensics -->
```manual target=analyst
Review the identified malicious rows. Verify if the host performed internal lateral movement via SSH or accessed M365 environments via proxy traffic. Identify the source of the initial appliance login.
```
→ final-close-out
## final-close-out
<!-- Final close out -->
```manual target=analyst
Document the findings, including any gaps in appliance logging or agent coverage. Recommend updating sudoers policies on similar appliances.
```
→ 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.