BeyondTrust Remote Support CVE-2026-102764: ARMORY CASTLE Zero-Day, SAWFLY and BARECLAW
Executive Summary
CVE-2026-102764 (CVSS 4.0 9.3, CWE-290) is a flaw in internal components of BeyondTrust Remote Support that did not adequately validate the origin of the messages they received; under the right conditions a remote attacker could perform file operations on the appliance. Every release up to and including 26.2.3 is affected. BeyondTrust patched its SaaS tenants on 2026-10-09 and published the BT26-05-RS patch for self-hosted releases 24.3.1 and later; older releases must be upgraded first. CISA added the CVE to the KEV catalog on 2026-10-16 with a federal due date of 2026-10-19.
Mandiant and GTIG found the flaw exploited as a zero-day by ARMORY CASTLE, a suspected PRC-nexus espionage actor formerly tracked as UNC5221 (SecurityWeek and The Hacker News also name WARP PANDA). Per the vendor timeline in the press reports, exploitation began on 2026-08-29. After exploitation the operator made POST requests to a staging webshell path, dropped the SAWFLY PHP webshell, copied /bin/sh to a SUID-root /usr/bin/dbus-authd, dumped the credential vault with the appliance's own bt-secrets utility, planted a boot script that restores passwordless root through sudoers.template, deleted logs, and published a BARECLAW SOCKS5-over-WebSocket tunneler through a hidden HAProxy route. With stolen Administrator credentials the operator then raised an account's Jump Item and Team roles from No Access to Administrator, opened remote support sessions to internal endpoints, and used the built-in file-transfer service to pull documents such as software inventories off user desktops.
What a Falcon sensor can and cannot see. The appliance runs no Falcon sensor, and Mandiant states that customers cannot audit its host file system; the exploitation evidence sits in logs that are only accessible through a LUKS-encrypted partition. So the exploit, SAWFLY, BARECLAW, the SUID shell, the persistence script, the vault dump and the log deletion are not Falcon-queryable. They are handled here as appliance-log and forensic-triage items (section 7) and as a coverage gap (section 15). What the sensor can see is downstream: the BeyondTrust agent on internal Windows endpoints, the processes a support session starts, the agent's network destinations, and inbound connections or logons that arrive from the appliance's address when the SOCKS5 tunnel is used. The CQL in section 8 is built on that surface. File reads and the file-transfer payload itself are invisible to endpoint telemetry.
Source Review & Web Hunter Notes
| Tier | Source | Key Finding | Carry |
|---|---|---|---|
| 1 · Threat intel | Google Threat Intelligence Group / Mandiant, "ARMORY CASTLE Exploits BeyondTrust", 2026-10-15 (snapshot 01) | Incident-response report: zero-day exploitation in late August 2026, SAWFLY webshell, BARECLAW tunneler, SUID shell, vault extraction, boot-script persistence, log deletion, HAProxy backdoor, admin-session abuse, remote sessions and file transfer from internal desktops. Source of both file hashes, the file names, the commands and the HAProxy strings. Includes YARA rules and remediation steps. | yes |
| 1 · Registry | NVD record CVE-2026-102764 (snapshot 02) | Published 2026-10-15. Description (improper origin validation, file operations on the appliance), affected range up to 26.2.3, CVSS 4.0 9.3 from the CVE source (CNA), CVSS 3.1 9.8 from NVD, SSVC exploitation: active. | yes |
| 1 · Government | CISA alert, 2026-10-16 (snapshot 03) | Active exploitation confirmed, KEV addition, patch and isolation guidance, rebuild from a known-good state, rotate every credential the appliance stored or injected, review new MFA registrations on privileged accounts. Calls the flaw an authentication bypass. | yes |
| 1 · Government | CISA KEV catalog entry (snapshot 06) | Added 2026-10-16, due 2026-10-19, CWE-290, "forensicTriage: Yes", ransomware use unknown. | yes |
| 2 · News | The Hacker News, 2026-10-16 (snapshot 04) | Quotes BeyondTrust's advisory and timeline: exploitation on 2026-08-29, public exploitation of another security device provider on 2026-09-27, SaaS patched 2026-10-09. Names WARP PANDA. Re-reports Mandiant; not independent for TTPs. | yes |
| 2 · News | SecurityWeek, 2026-10-16 (snapshot 05) | Adds the vendor timeline detail (identified 2026-09-28, patch built 2026-09-30, shipped 2026-10-08), one hosted and one self-hosted appliance hit on 2026-08-29, and earlier ARMORY CASTLE edge-device zero-days. Re-reports Mandiant for TTPs. | yes |
| 1 · Vendor | BeyondTrust advisory BT26-05 and blog "ARMORY CASTLE and BT26-05" (not snapshotted) | Could not be fetched: both URLs returned HTTP 403 from the vendor's bot protection, and this build does not bypass it. Their content reached this pack only through the NVD record, the KEV entry, CISA, Mandiant and the two news articles that quote them. Nothing in the pack depends on the vendor page alone. | no |
Decisions: (1) Nothing ships as prevent. The two SHA-256 values appear only in the Mandiant report; the news articles carry no hashes. Single-sourced indicators ship detect. (2) The BeyondTrust agent, the Jump Client and the appliance files that were abused (bt-secrets, bt-sysconfig, haproxy.conf, sudoers.template, /bin/sh) are stock product components or system files: they appear only as hunt locations or behaviors, never as block targets. (3) Only names the sources use appear here: ARMORY CASTLE, UNC5221, WARP PANDA, SAWFLY, BARECLAW. UNC5221's earlier BRICKSTORM and Microsoft 365 activity is a different campaign, covered by another pack, and none of its indicators are included. (4) Sources disagree on two points and both are shown: CISA and the KEV entry say "authentication bypass" while the NVD record, The Hacker News and SecurityWeek say improper origin validation allowing file operations; and The Hacker News says one self-hosted appliance was hit on 2026-08-29 while SecurityWeek says one hosted and one self-hosted. (5) No source contained text directed at an AI agent, any instruction to run commands, or any request to fetch further URLs.
Not used: the BeyondTrust pages (blocked, see above). Third-party blogs surfaced by search (DEV Community, SC World, ThreatCluster and others) were not fetched and are not cited. The vendor's remark that the actor keeps a model of its target products in an AI context (quoted by The Hacker News) is an unverified working assessment and drives no detection.
Hunt Brief & Attack Chain
Working hypothesis: An internet-reachable Remote Support appliance on 26.2.3 or earlier is exploited without credentials, giving file operations that the operator turns into a webshell, root, the credential vault and a hidden SOCKS5 tunnel. From the compromised appliance the operator logs into the administrative portal as Administrator, raises an account's Jump Item and Team roles, and uses ordinary remote support sessions to reach internal desktops. The appliance steps are invisible to an endpoint sensor. The downstream steps run on sensored Windows hosts as the BeyondTrust agent and its children, and as connections and logons that originate from the appliance's address.
| Step | Behavior | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 · Exploit | Unauthenticated message-origin flaw lets the attacker perform file operations on the appliance | Appliance web and application logs (only inside an encrypted partition that customers cannot audit); reverse proxy, WAF or perimeter firewall logs for the exposure window (outside endpoint telemetry) | GAP N3 on proxy or WAF logs; N6 with the vendor |
| 2 · Staging | POST requests to /app_84304470%2Ephp; about 11 minutes later SAWFLY (mangoapi.php) is created under the web root | Reverse proxy or WAF request paths (outside endpoint telemetry); appliance file system (not customer-auditable) | GAP N3, N6 |
| 3 · Webshell C2 | SAWFLY accepts an obfuscated POST parameter _c94mfe, Base32 and RC4 transport, runs code with eval | Reverse proxy or WAF request logs only if request bodies or parameters are logged (outside endpoint telemetry) | GAP N3 |
| 4 · Root | /bin/sh copied to /usr/bin/dbus-authd, chowned root, SUID set | Appliance file system (not customer-auditable) | GAP N6 only |
| 5 · Credentials | bt-secrets get ... vault run three ways; bt-secrets.log* deleted | Appliance message log and file system (not customer-auditable). Consequence: credential replay on endpoints (logon events) | GAP for the dump; Q6 for replay |
| 6 · Persistence | post_boot.d/zz-root-persist appends a NOPASSWD line to sudoers.template and runs bt-sysconfig --no-restart misc | Appliance file system (not customer-auditable) | GAP N6 only |
| 7 · Tunnel | /tmp/ingredi_ws --listen 19800 ... --ws-path /uidchanarge; HAProxy ACL wswsws routes /uidchanarge to backend webskd3 at 127.0.0.1:19800 | Proxy or WAF logs show WebSocket upgrades to the path (outside endpoint telemetry). Consequence on endpoints: inbound connections and logons from the appliance's address (CrowdStrike: NetworkReceiveAcceptIP4, UserLogon. SentinelOne: IP Connect, Login. Defender: DeviceNetworkEvents, DeviceLogonEvents) | GAP for the tunnel; Q5, Q6 for the pivot; N3 |
| 8 · Anti-forensics | Bulk rm of /ns/log/*.log, /var/log/messages and /tmp/sshauth.* | Gaps in forwarded appliance syslog (outside endpoint telemetry) | GAP N4 |
| 9 · Admin session abuse | Stolen Administrator login to the web admin portal; account's Jump Item and Team roles raised from No Access to Administrator | Forwarded appliance syslog events login and user_changed (outside endpoint telemetry) | GAP N1, N2 |
| 10 · Remote session | Remote support session to an internal endpoint with full file-system access | Process creation with command line, path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); outbound network connection (CrowdStrike: NetworkConnectIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents) | Q1, Q2, Q3, Q4 |
| 11 · File transfer | Documents such as software inventories downloaded from the user's desktop through the built-in file-transfer service | File reads and transferred bytes are not recorded by endpoint telemetry. File writes by the agent are (CrowdStrike: PeFileWritten, NewExecutableWritten, ZipFileWritten. SentinelOne: File Creation. Defender: DeviceFileEvents) | GAP for reads and volume; N5 session report; Q7 for writes only |
Hunt hypotheses (fidelity-ordered)
- H1 (high confidence, expected zero): The published hashes, tool names or distinctive command-line tokens appear on any sensored host, which would mean a sample or lookalike left the appliance → Q8.
- H2 (medium): A workstation or server accepts a connection, or sees a network or remote-interactive logon, from the appliance's address, which is the SOCKS5 pivot or credential replay → Q5, Q6.
- H3 (medium): The BeyondTrust agent spawns shells, discovery tools or archivers, alone or several in a day, outside a known help desk pattern → Q2, Q3.
- H4 (low): The agent writes executables or archives to disk, general remote-support abuse not reported here → Q7.
- H5 (baseline): Agent names, hosts and destinations are known, and every agent talks only to your appliance or the vendor's cloud → Q1, Q4.
- H6 (non-Falcon): Role elevation, unexplained admin logins, tunnel and webshell paths in proxy logs, syslog gaps and appliance artifacts → N1 to N6.
Consolidated IOC Table
| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| SHA-256 | dc14e215269a93fdbc4c1a80b984c23faf7af0911c6dbb85309796a6f2ae95fb | high | detect | SAWFLY obfuscated PHP webshell mangoapi.php (snapshot 01 File Indicators). Appliance-resident; single source. |
| SHA-256 | 1f19b9a27d79c11bda00a1e8faf74a7fdd683d38ccef1b60df2fd0307e3aa462 | high | detect | BARECLAW SOCKS5 WebSocket tunneler ingredi_ws (snapshot 01). Appliance-resident ELF; single source. |
| Filename | mangoapi.php | high | hunt | SAWFLY webshell, created under /%SITE_SERVICE_ACCOUNT%/ingredi/app/laravel/public/ (snapshot 01). |
| Filename | ingredi_ws | high | hunt | BARECLAW binary, run from /tmp (snapshot 01). |
| URL path | /app_84304470%2Ephp | high | hunt | POST target used right after exploitation; the file was not recovered (snapshot 01). Match the encoded and decoded dot. |
| POST parameter | _c94mfe | high | hunt | SAWFLY command parameter; absent parameter returns 404 (snapshot 01). Visible only if the proxy or WAF logs parameters. |
| URL path | /uidchanarge | high | hunt | BARECLAW WebSocket endpoint exposed by HAProxy (snapshot 01). Operator-chosen; trivially changed. |
| Port | 19800 | medium | hunt | BARECLAW listener, bound to 127.0.0.1 on the appliance (snapshot 01). Not reachable from the network. |
| File path | /usr/bin/dbus-authd | high | hunt | Copy of /bin/sh with root ownership and SUID bit (snapshot 01). Appliance-resident. |
| File path | /home/bomgar/sbin/post_boot.d/zz-root-persist | high | hunt | Boot script that restores passwordless root via the sudoers template (snapshot 01). Appliance-resident. |
| Config line | %SITE_SERVICE_ACCOUNT% ALL=(ALL) NOPASSWD: ALL | high | hunt | Appended to /ns/config/sudoers.template (snapshot 01). Appliance-resident. |
| Config line | acl wswsws path /uidchanarge; use_backend webskd3 if wswsws; backend webskd3 server websocks5srv 127.0.0.1:19800 | high | hunt | HAProxy backdoor in /ns/config/haproxy.conf (snapshot 01). Appliance-resident. |
| Command | /ns/sbin/bt-secrets get ... vault; rm -f /home/bomgar/log/bt-secrets.log* | high | hunt | Vault dump and log removal (snapshot 01). bt-secrets is a stock utility: the behavior, not the binary, is the signal. |
| Command | /tmp/ingredi_ws --listen 19800 --token ... --obfs -q --ws-path /uidchanarge | high | hunt | BARECLAW invocation; the token is redacted in the source (snapshot 01). |
| Syslog event | user_changed with jump_item_role default or teams raised from No Access to Administrator | high | hunt | Role elevation record (snapshot 01 Figure 7). Hunt in forwarded appliance syslog (N1). |
| Version | Remote Support <= 26.2.3 | high | detect | Affected range per NVD, CISA, SecurityWeek and Mandiant (snapshots 01, 02, 03, 05). Fixed by BT26-05-RS. |
Affected Surface & Telemetry Matrix
| Surface | Telemetry | Priority | Gap |
|---|---|---|---|
| Self-hosted Remote Support appliance (all releases up to 26.2.3), internet-reachable | Forwarded appliance syslog and session events; reverse proxy, WAF and perimeter firewall logs for the exposure window | critical | No endpoint sensor on the appliance. Customers cannot audit its host file system; exploitation evidence sits in logs inside an encrypted partition, and the actor deleted on-appliance logs. Outside endpoint telemetry entirely. |
| BeyondTrust-hosted (SaaS) Remote Support | Tenant audit and session reports from the console | medium | Vendor patched all tenants on 2026-10-09; the credential, role and session review still applies. SecurityWeek reports one hosted instance among the first victims. |
| Windows endpoints running a Jump Client or customer client (the support targets) | Process creation with command line, path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); outbound network connection (CrowdStrike: NetworkConnectIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents) | high | Agent process names are not in any cited source: validate with Q1. File reads and file-transfer volume are not recorded. Session identity (which operator) is only in appliance reports. |
| Jumpoint hosts and representative console workstations | Same process and network telemetry; user logon (CrowdStrike: UserLogon. SentinelOne: Login. Defender: DeviceLogonEvents) | medium | Mandiant tells defenders to redeploy Jumpoints and the console from the rebuilt appliance; hunt them as endpoints in scope. No source reports them as compromised. |
| Servers the appliance is integrated with (directory, syslog, mail, ITSM) | Inbound accept (CrowdStrike: NetworkReceiveAcceptIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents); user logon | medium | They legitimately receive appliance traffic: use them as the exclusion list for Q5 and Q6. Inbound-accept logging depends on sensor policy. |
| All other internal hosts the appliance can route to | Inbound accept and user logon, as above | high | These are where SOCKS5 pivot traffic and credential replay land. Restrict the appliance's egress (section 12) so this surface shrinks. |
ATT&CK Mapping
| Tactic | Technique | Observed behavior | Query or control |
|---|---|---|---|
| Initial Access | T1190 Exploit Public-Facing Application | Zero-day against the Remote Support appliance (CVE-2026-102764) | Patch; N3; vendor review (N6) |
| Persistence | T1505.003 Web Shell | SAWFLY mangoapi.php under the web root | N3, N6; Q8 for copies |
| Persistence | T1037 Boot or Logon Initialization Scripts | post_boot.d/zz-root-persist restores root at startup | N6 |
| Privilege Escalation | T1548.001 Setuid and Setgid; T1548.003 Sudo and Sudo Caching | SUID copy of /bin/sh at /usr/bin/dbus-authd; NOPASSWD line in sudoers.template | N6; Q8 tokens |
| Credential Access | T1555 Credentials from Password Stores | bt-secrets get ... vault on the appliance | N6; Q6 for replay |
| Defense Evasion | T1070.004 File Deletion; T1027 Obfuscated Files or Information | Bulk log deletion; obfuscated webshell; XOR-obfuscated tunnel | N4; Q8 |
| Command and Control | T1090 Proxy; T1572 Protocol Tunneling; T1573.001 Symmetric Cryptography | BARECLAW SOCKS5 over WebSocket behind HAProxy; SAWFLY RC4 and Base32 transport | N3; Q5, Q6 |
| Valid Accounts / Persistence | T1078 Valid Accounts; T1098 Account Manipulation | Stolen Administrator login; Jump Item and Team role raised to Administrator | N1, N2 |
| Lateral Movement | T1219 Remote Access Software; T1021 Remote Services | Remote support sessions to internal endpoints; pivot through the tunnel | Q1, Q2, Q3, Q4, Q5, Q6 |
| Discovery | T1082 System Information Discovery; T1083 File and Directory Discovery; T1518 Software Discovery | Full file-system access; interest in software inventories | Q2, Q3 |
| Collection / Exfiltration | T1005 Data from Local System; T1041 Exfiltration Over C2 Channel | Built-in file-transfer service pulls documents from user desktops | N5 session report; GAP in endpoint telemetry |
| Resource use | T1105 Ingress Tool Transfer | Not reported; general abuse of the same channel | Q7 (low confidence) |
Native Audit-Log Hunts & Appliance Forensic Triage
Non-CQL checks. These cover what Falcon cannot see. N1 to N4 run against appliance syslog and proxy or WAF logs you have forwarded to a SIEM or log store. N5 is a console review. N6 is a forensic-triage list for BeyondTrust Support or your IR firm on a disk image: Mandiant states customers cannot audit the appliance host file system, so do not run anything on the live appliance. Everything here is read-only. Log formats are assumptions and are flagged where they matter.
N1 · Role elevation in forwarded appliance syslog (Jump Item or Team role raised to Administrator)
# N1. Run over exported appliance syslog (JSON payloads as shown in Mandiant Figure 7). Strip any syslog header first if present.
# Events where a Jump Item or Team role became Administrator:
jq -c 'select(.event=="user_changed")
| select(.["new_permissions:jump_item_role:default:name"]=="Administrator"
or .["new_permissions:jump_item_role:teams:name"]=="Administrator")' appliance-syslog.jsonl
# Fallback without jq:
grep -E '"event": ?"user_changed"' appliance-syslog.jsonl | grep -E 'jump_item_role:(default|teams):name": ?"Administrator"'
# Also review every user_added, api_account and security_provider event, and any change to outbound event or syslog destinations,
# that has no change ticket (Mandiant detection guidance, snapshot 01).
N2 · Administrator logins to the web portal, by source address
# N2. Successful web admin logins and where they came from (assumes JSON-lines syslog payloads; adjust to your forwarder). grep -E '"event": ?"login"' appliance-syslog.jsonl | grep -E '"status": ?"success"' | grep 'web/login' \ | grep -oE '"who_ip": ?"[^"]*"' | sort | uniq -c | sort -rn # Review: addresses in residential-broadband or commercial-VPN space, and logins outside business hours. # Mandiant notes the operator used commercial VPN exit nodes and compromised home and small-office routers (snapshot 04).
N3 · Reverse proxy or WAF log hunt for the published paths and tunnel
# N3. Run on the reverse proxy or WAF in front of the appliance (the appliance cannot alter these logs).
# Assumes nginx/Apache combined log format (request path is field 7, status is field 9); adjust for your layout.
# Published staging webshell path (match the encoded and the decoded dot), SAWFLY parameter, BARECLAW WebSocket path:
grep -hE 'app_84304470(%2[eE]|\.)php|_c94mfe|uidchanarge' /var/log/nginx/access.log* 2>/dev/null
# Paths outside the known Remote Support set, especially .php (baseline your normal paths first):
awk '{print $7}' /var/log/nginx/access.log* 2>/dev/null | grep -iE '\.php' | sort | uniq -c | sort -n
# WebSocket upgrades (HTTP 101) from addresses that are not support staff or your endpoint ranges:
awk '$9==101 {print $1, $7}' /var/log/nginx/access.log* 2>/dev/null | sort | uniq -c | sort -rn
N4 · Gaps in forwarded appliance syslog (log deletion indicator)
# N4. Count forwarded appliance syslog lines per hour; a silent hour inside a busy day, or a gap bounded by one session, is the signal. # Assumes each line starts with an ISO-8601 timestamp (YYYY-MM-DDTHH:...). Adjust the cut width to your format. cut -c1-13 appliance-syslog.log | sort | uniq -c # Mandiant: "an interruption bounded by a single session is a strong indicator of log tampering" (snapshot 01). # Also confirm syslog forwarding itself is still configured: the actor could have changed the destination.
N5 · Support session and file-transfer review (console)
- In the console, export session, team-activity and user-audit reports for 2026-08-29 to today. Mandiant: "every endpoint touched is in scope for downstream hunting" (snapshot 01).
- List sessions started by any account whose role changed in the window (N1), sessions outside business hours, and every file-transfer event. Record the Jump Item, the endpoint, the operator account and the time.
- Feed each endpoint into Q2, Q3 and Q7 by
aidorComputerNamefor those timestamps. This is the only record of which files left; the endpoint sensor does not log reads or transfer volume.
N6 · Appliance forensic triage (vendor or IR on a disk image, never on the live appliance)
# N6. Appliance-resident artifacts to check on a FORENSIC COPY of the appliance disk, mounted read-only. Not Falcon-queryable. # Customers cannot audit the appliance host; engage BeyondTrust Support or your IR firm. Preserve first (virtual: snapshot with memory, # export disk; hardware and SaaS: request preservation through BeyondTrust Support) before any change or reboot. IMG=/mnt/appliance_image find "$IMG/usr/bin" -name dbus-authd -perm -4000 -ls # SUID copy of /bin/sh ls -la "$IMG/home/bomgar/sbin/post_boot.d/" # zz-root-persist grep -n 'NOPASSWD' "$IMG/ns/config/sudoers.template" # appended NOPASSWD line for the site service account grep -n -E 'wswsws|webskd3|19800|uidchanarge' "$IMG/ns/config/haproxy.conf" # ACL, backend, loopback route find "$IMG/tmp" -name 'ingredi_ws*' -ls # BARECLAW find "$IMG" -name 'mangoapi.php' -ls # SAWFLY under the web root sha256sum "$IMG"/tmp/ingredi_ws 2>/dev/null # compare with the published SHA-256 values in section 10 ls -la "$IMG/home/bomgar/log" "$IMG/ns/log" "$IMG/var/log" # expect missing or truncated logs # Mandiant YARA rules G_Hunting_Webshell_SAWFLY_1 and G_Hunting_Backdoor_BARECLAW_1 are in snapshot 01 for scanning the image.
Hunt Queries: CrowdStrike CQL, SentinelOne PowerQuery and Defender XDR KQL
Use your tenant's own address. SentinelOne does not document a link that pre-fills a query, so each "Copy & open SentinelOne" button copies the query and opens this console: paste it into PowerQuery.
Pick your portal. Microsoft documents a Share link in advanced hunting but not its URL format, so each "Copy & open Defender" button copies the query and opens Advanced hunting: paste it into the editor.
REPLACE_WITH_APPLIANCE_IP that you must replace with the address(es) Q4 shows; an unedited placeholder returns zero rows forever; (3) inbound-accept events depend on sensor policy, so test with a known connection. Events and fields were checked against the crowdstrike-logscale-v3 references: ProcessRollup2, SyntheticProcessRollup2, NetworkConnectIP4, NetworkReceiveAcceptIP4, UserLogon, PeFileWritten, NewExecutableWritten, ZipFileWritten. Queries carry a // LOOKBACK note: set that window in the console time picker.Looks for: Which Windows hosts run a BeyondTrust Jump Client or customer client, and under what process names and install paths. This is the readiness query, not a detection. The agent name pattern bomgar*.exe / beyondtrust*.exe is an analyst-supplied product naming convention that appears in no cited source. Run this first and amend the pattern used by Q2, Q3, Q4 and Q7 to match what your fleet actually shows. A name pattern that matches nothing returns zero rows forever.
Known limitations and deployment notes
- PowerQuery: Processes already running when the sensor started (the CQL also reads the synthetic start-up event) are not in Process Creation events.
- PowerQuery assumes: tgt.process.image.path holds the full image path of the created process.
- PowerQuery assumes: hosts uses estimate_distinct, an estimate rather than an exact count.
- KQL – Defender XDR: A process the sensor did not observe starting is not captured.
- KQL – Defender XDR assumes: FolderPath holds the full image path of the created process.
- KQL – Defender XDR assumes: Hosts uses dcount, an estimate rather than an exact count.
// HUNT: BeyondTrust Remote Support agent inventory and process-name baseline // MITRE: T1219 // CONF: low | FP: low | COST: medium | REQUIRES: ProcessRollup2 on Windows endpoints that run a Jump Client or customer client // SOURCE: product naming convention, analyst-supplied (NOT in any cited source). Amend the agent pattern in Q2 to Q4 and Q7 from this output // FALSE POSITIVES: none; this is an inventory, not an alert // LOOKBACK: 30d #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | (FileName=/^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$/i or ImageFileName=/\\(bomgar|beyondtrust)/i) | groupBy([FileName, ImageFileName], function=[count(aid, distinct=true, as=Hosts), count(as=Execs)], limit=200) | sort(Hosts, order=desc, limit=100)
3 required fields · View requirements
Required telemetry
- Process Creation
Required fields
tgt.process.name: Created process nametgt.process.image.path: Created process image pathagent.uuid: Endpoint identifier
Fallbacks
agent.uuid→endpoint.name: Changes how hosts are counted: renamed hosts count twice.
Readiness test
event.type = 'Process Creation' tgt.process.name = * | limit 5 | columns event.time, tgt.process.name, tgt.process.image.path, agent.uuid
// HUNT: BeyondTrust Remote Support agent inventory and process-name baseline // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1219 // CONF: low | FP: low // FALSE POSITIVES: none; this is an inventory, not an alert // EQUIVALENCE: equivalent-with-schema-assumptions - Same inventory: processes whose name matches the BeyondTrust agent pattern, or whose image path has a directory or file component starting with that pattern, grouped by name and path with a distinct-host count. matches is case-insensitive, which reproduces the CQL /i intent. The created process is tgt.process on a Process Creation event. // REQUIRES: SentinelOne process-creation telemetry with image path // TUNING: Inventory only, not an alert. Review the names and paths, then amend the agent pattern used by the later queries. // LOOKBACK: 30d; set the console time picker, the published query carries no time predicate // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Processes already running when the sensor started (the CQL also reads the synthetic start-up event) are not in Process Creation events. // VALIDATION LEVEL: static-reviewed event.type = 'Process Creation' and (tgt.process.name matches '^(bomgar|beyondtrust)[-_a-z0-9.]*\\.exe$' or tgt.process.image.path matches '\\\\(bomgar|beyondtrust)') | group execs=count(), hosts=estimate_distinct(agent.uuid) by tgt.process.name, tgt.process.image.path | sort -hosts | limit 100
Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameFolderPath: Created process pathDeviceId: Device identifier
Fallbacks
DeviceId→DeviceName: Changes how hosts are counted: renamed devices count twice.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, FolderPath, DeviceId | take 5
// HUNT: BeyondTrust Remote Support agent inventory and process-name baseline // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1219 // CONF: low | FP: low // FALSE POSITIVES: none; this is an inventory, not an alert // EQUIVALENCE: equivalent-with-schema-assumptions - Same inventory: created processes whose name matches the BeyondTrust agent pattern, or whose path has a component starting with it, grouped by name and path with a distinct-device count. matches regex with (?i) reproduces the CQL /i intent. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents) // TUNING: Inventory only, not an alert. Review the names and paths, then amend the agent pattern used by the later queries. // LOOKBACK: 30d (Advanced Hunting retention is 30 days; the CQL tab uses the same 30d) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A process the sensor did not observe starting is not captured. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0 DeviceProcessEvents | where Timestamp >= ago(30d) | where FileName matches regex @"(?i)^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$" or FolderPath matches regex @"(?i)\\(bomgar|beyondtrust)" | summarize Execs = count(), Hosts = dcount(DeviceId), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by FileName, FolderPath | sort by Hosts desc | take 100
Looks for: A process whose parent is the BeyondTrust agent and whose image is a shell, scripting host, LOLBin, discovery or archive tool. The reported operator opened remote support sessions to internal endpoints and obtained full file-system access (snapshot 01). The sensor sees the child processes the session starts; it does not see the file transfer itself (see Q7 and the coverage gaps). FP: Help desk staff use the console command shell and remote PowerShell legitimately, so every session can look like this. Baseline per host for 30 days, exclude the exact command lines your help desk runs, and reconcile every remaining hit against the appliance session report (who, when, which Jump Item).
Known limitations and deployment notes
- PowerQuery: Help desk activity that goes through a different agent executable name than the pattern is not captured; widen the pattern from Q1.
- PowerQuery assumes: src.process.user holds the account of the creating process.
- KQL – Defender XDR: Help desk activity that goes through a different agent executable name than the pattern is not captured; widen the pattern from Q1.
- KQL – Defender XDR assumes: InitiatingProcessFileName holds the name of the agent process that created the tool.
// HUNT: BeyondTrust agent spawns a shell, recon, download or archive tool // MITRE: T1219 | T1059.003 | T1059.001 | T1082 | T1083 | T1105 | T1560.001 // CONF: medium | FP: medium | COST: low | REQUIRES: ProcessRollup2 with ParentBaseFileName and CommandLine; agent pattern validated with Q1 // FALSE POSITIVES: help desk console command shell, remote PowerShell and scripted fixes during a legitimate support session // TUNING: baseline by ComputerName and CommandLine for 30 days, exclude your help desk's exact command lines, then reconcile each remaining hit with the appliance session report (who, when, Jump Item) // LOOKBACK: 7d #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | ParentBaseFileName=/^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$/i | FileName=/^(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|wmic|nltest|net1?|whoami|systeminfo|ipconfig|tasklist|reg|arp|netstat|7z|7za|rar|tar)\.exe$/i | table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, aid], limit=500)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timesrc.process.name: Creator process nametgt.process.name: Created process nametgt.process.cmdline: Created command line
Recommended fields
src.process.user: Creator account
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Process Creation' src.process.name = * | limit 5 | columns event.time, src.process.name, tgt.process.name, tgt.process.cmdline
// HUNT: BeyondTrust agent spawns a shell, recon, download or archive tool // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1219, T1059.003, T1059.001, T1082, T1083, T1105, T1560.001 // CONF: medium | FP: medium // FALSE POSITIVES: help desk console command shell, remote PowerShell and scripted fixes during a legitimate support session // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: a shell, recon, download or archive tool created by a process matching the BeyondTrust agent pattern. The creator is src.process and the new process is tgt.process on a Process Creation event. matches is case-insensitive, which reproduces the CQL /i intent. // REQUIRES: SentinelOne process-creation telemetry with creator process name and command line; agent pattern validated with Q1 // TUNING: Baseline by host and command line for 30 days, exclude the help desk's exact command lines, then reconcile each remaining hit with the appliance session report (who, when, Jump Item). // LOOKBACK: 7d; set the console time picker, the published query carries no time predicate // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Help desk activity that goes through a different agent executable name than the pattern is not captured; widen the pattern from Q1. // VALIDATION LEVEL: static-reviewed event.type = 'Process Creation' and src.process.name matches '^(bomgar|beyondtrust)[-_a-z0-9.]*\\.exe$' and tgt.process.name matches '^(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|wmic|nltest|net1?|whoami|systeminfo|ipconfig|tasklist|reg|arp|netstat|7z|7za|rar|tar)\\.exe$' | columns event.time, endpoint.name, src.process.user, src.process.name, tgt.process.name, tgt.process.cmdline, agent.uuid | sort -event.time | limit 500
Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeInitiatingProcessFileName: Initiating processFileName: Created process nameProcessCommandLine: Created command line
Recommended fields
AccountName: Account
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, InitiatingProcessFileName, FileName, ProcessCommandLine | take 5
// HUNT: BeyondTrust agent spawns a shell, recon, download or archive tool // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1219, T1059.003, T1059.001, T1082, T1083, T1105, T1560.001 // CONF: medium | FP: medium // FALSE POSITIVES: help desk console command shell, remote PowerShell and scripted fixes during a legitimate support session // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: a shell, recon, download or archive tool created by a process matching the BeyondTrust agent pattern. The creator is InitiatingProcessFileName and the new process is FileName. matches regex with (?i) reproduces the CQL /i intent. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents); agent pattern validated with Q1 // TUNING: Baseline by device and command line for 30 days, exclude the help desk's exact command lines, then reconcile each remaining hit with the appliance session report (who, when, Jump Item). // LOOKBACK: 7d; extend to 30d for the incident window // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Help desk activity that goes through a different agent executable name than the pattern is not captured; widen the pattern from Q1. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceProcessEvents | where Timestamp >= ago(7d) | where InitiatingProcessFileName matches regex @"(?i)^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$" | where FileName matches regex @"(?i)^(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|wmic|nltest|net1?|whoami|systeminfo|ipconfig|tasklist|reg|arp|netstat|7z|7za|rar|tar)\.exe$" | project Timestamp, ReportId, DeviceId, DeviceName, AccountName, InitiatingProcessFileName, FileName, ProcessCommandLine | sort by Timestamp desc | take 500
Looks for: The same agent-parent filter as Q2, aggregated per host per day, keeping hosts where the session started four or more different tools. A session that runs whoami, systeminfo, ipconfig, tasklist and an archiver in one day looks like the reconnaissance sweep the operator performed (software inventories, internal documents; snapshot 01), but routine triage looks the same. FP: Break-fix sessions that run several diagnostic commands. Raise the threshold, or exclude hosts and accounts that belong to help desk workstations, and pair every hit with the appliance session report.
Known limitations and deployment notes
- PowerQuery: The full list of tool names is not returned; example_tool shows one, so pull the rest with Q2 for the flagged host and day.
- PowerQuery assumes: The day bucket is a UTC day, as in the CQL.
- PowerQuery assumes: Tool names are lower-cased before counting, so a name that differs only in case counts once.
- KQL – Defender XDR: A burst split across two UTC days can fall under the threshold on both.
- KQL – Defender XDR assumes: The day bucket is a UTC day, as in the CQL.
- KQL – Defender XDR assumes: dcount is an estimate; at this cardinality it is exact in practice.
// HUNT: Support-session burst under the BeyondTrust agent (distinct tools per host per day) // MITRE: T1219 | T1082 | T1083 | T1005 // CONF: medium | FP: medium | COST: low | REQUIRES: ProcessRollup2 with ParentBaseFileName; agent pattern validated with Q1 // FALSE POSITIVES: routine break-fix sessions that run several diagnostic commands // TUNING: raise the distinct-tool threshold from 4 after a 30-day baseline, exclude known help desk endpoints by aid, and confirm each hit against the appliance session report // LOOKBACK: 7d #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | ParentBaseFileName=/^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$/i | FileName=/^(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|wmic|nltest|net1?|whoami|systeminfo|ipconfig|tasklist|reg|arp|netstat|7z|7za|rar|tar)\.exe$/i | Day := formatTime("%Y-%m-%d", field=@timestamp) | groupBy([aid, ComputerName, Day], function=[count(FileName, distinct=true, as=DistinctTools), count(as=Execs), collect([FileName]), min(@timestamp, as=First), max(@timestamp, as=Last)], limit=500) | test(DistinctTools >= 4) | FirstSeen := formatTime("%Y-%m-%d %H:%M:%S", field=First) | LastSeen := formatTime("%Y-%m-%d %H:%M:%S", field=Last) | sort(DistinctTools, order=desc, limit=100) | table([ComputerName, Day, DistinctTools, Execs, FileName, FirstSeen, LastSeen, aid], limit=100)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timesrc.process.name: Creator process nametgt.process.name: Created process nameagent.uuid: Endpoint identifier
Recommended fields
endpoint.name: Host name
Fallbacks
agent.uuid→endpoint.name: Changes how hosts are grouped: renamed hosts split.
Readiness test
event.type = 'Process Creation' src.process.name = * | limit 5 | columns event.time, agent.uuid, src.process.name, tgt.process.name
// HUNT: Support-session burst under the BeyondTrust agent (distinct tools per host per day)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1219, T1082, T1083, T1005
// CONF: medium | FP: medium
// FALSE POSITIVES: routine break-fix sessions that run several diagnostic commands
// EQUIVALENCE: approximate-analytic - Same burst analytic: four or more distinct tools created by the BeyondTrust agent on one host in one day. Two group stages give an exact distinct-tool count, but the CQL's collected list of tool names becomes a single example tool, and tool names are lower-cased before counting.
// REQUIRES: SentinelOne process-creation telemetry with creator process name; agent pattern validated with Q1
// TUNING: Raise the distinct-tool threshold from 4 after a 30-day baseline, exclude known help desk endpoints by agent.uuid, and confirm each hit against the appliance session report.
// LOOKBACK: 7d; set the console time picker, the published query carries no time predicate
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: The full list of tool names is not returned; example_tool shows one, so pull the rest with Q2 for the flagged host and day.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' and src.process.name matches '^(bomgar|beyondtrust)[-_a-z0-9.]*\\.exe$' and tgt.process.name matches '^(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|wmic|nltest|net1?|whoami|systeminfo|ipconfig|tasklist|reg|arp|netstat|7z|7za|rar|tar)\\.exe$'
| group execs=count(), t_first=min(event.time), t_last=max(event.time) by agent.uuid, endpoint.name, day_bucket=timebucket('1d'), tool=lower(tgt.process.name)
| group distinct_tools=count(), total_execs=sum(execs), example_tool=any(tool), first_seen=min(t_first), last_seen=max(t_last) by agent.uuid, endpoint.name, day_bucket
| filter distinct_tools >= 4
| sort -distinct_tools
| limit 100Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeInitiatingProcessFileName: Initiating processFileName: Created process nameDeviceId: Device identifier
Recommended fields
DeviceName: Host name
Fallbacks
DeviceId→DeviceName: Changes how devices are grouped: renamed devices split.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, DeviceId, InitiatingProcessFileName, FileName | take 5
// HUNT: Support-session burst under the BeyondTrust agent (distinct tools per host per day) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1219, T1082, T1083, T1005 // CONF: medium | FP: medium // FALSE POSITIVES: routine break-fix sessions that run several diagnostic commands // EQUIVALENCE: equivalent-with-schema-assumptions - Same burst analytic: four or more distinct tools created by the BeyondTrust agent on one device in one day, with the tool names collected. Names are lower-cased before counting and dcount is an estimate. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents); agent pattern validated with Q1 // TUNING: Raise the distinct-tool threshold from 4 after a 30-day baseline, exclude known help desk devices by DeviceId, and confirm each hit against the appliance session report. // LOOKBACK: 7d; extend to 30d for the incident window // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A burst split across two UTC days can fall under the threshold on both. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0 DeviceProcessEvents | where Timestamp >= ago(7d) | where InitiatingProcessFileName matches regex @"(?i)^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$" | where FileName matches regex @"(?i)^(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|wmic|nltest|net1?|whoami|systeminfo|ipconfig|tasklist|reg|arp|netstat|7z|7za|rar|tar)\.exe$" | summarize DistinctTools = dcount(tolower(FileName)), Execs = count(), Tools = make_set(tolower(FileName)), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by DeviceId, DeviceName, Day = bin(Timestamp, 1d) | where DistinctTools >= 4 | sort by DistinctTools desc | take 100
Looks for: Outbound destinations of the BeyondTrust agent process, ranked rarest first by distinct hosts. Use it to (1) list your real appliance address(es) so you can fill Q5 and Q6, (2) confirm that Jump Clients were redeployed to the rebuilt or patched appliance after a rebuild (Mandiant recommends redeploying them, snapshot 01), and (3) spot an agent talking to a destination that is not your appliance or the vendor's cloud.
Known limitations and deployment notes
- PowerQuery: Connections made through a proxy show the proxy address, not the appliance.
- PowerQuery assumes: IP Connect events are connections initiated by the acting process, so dst.ip.address is the remote end.
- PowerQuery assumes: hosts uses estimate_distinct, an estimate rather than an exact count.
- KQL – Defender XDR: Failed connection attempts are not listed.
- KQL – Defender XDR: Connections made through a proxy show the proxy address, not the appliance.
- KQL – Defender XDR assumes: ConnectionSuccess is the ActionType for an established outbound connection.
- KQL – Defender XDR assumes: dcount is an estimate; at this cardinality it is exact in practice.
// HUNT: BeyondTrust agent outbound destinations (appliance discovery and rogue-destination check) // MITRE: T1219 | T1071.001 // CONF: low | FP: low | COST: low | REQUIRES: NetworkConnectIP4 with ContextBaseFileName; agent pattern validated with Q1 // SOURCE: baseline and discovery query; no indicator is asserted // FALSE POSITIVES: none; this lists destinations for review // LOOKBACK: 30d #event_simpleName=NetworkConnectIP4 | ContextBaseFileName=/^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$/i | groupBy([RemoteAddressIP4, RemotePort], function=[count(aid, distinct=true, as=Hosts), count(as=Conns), min(@timestamp, as=First), max(@timestamp, as=Last)], limit=200) | FirstSeen := formatTime("%Y-%m-%d %H:%M:%S", field=First) | LastSeen := formatTime("%Y-%m-%d %H:%M:%S", field=Last) | sort(Hosts, order=asc, limit=100) | table([RemoteAddressIP4, RemotePort, Hosts, Conns, FirstSeen, LastSeen], limit=100)
5 required fields · View requirements
Required telemetry
- IP Connect
Required fields
event.time: Event timesrc.process.name: Acting process namedst.ip.address: Remote addressdst.port.number: Remote portagent.uuid: Endpoint identifier
Fallbacks
agent.uuid→endpoint.name: Changes how hosts are counted: renamed hosts count twice.
Readiness test
event.type = 'IP Connect' dst.ip.address = * | limit 5 | columns event.time, agent.uuid, src.process.name, dst.ip.address, dst.port.number
// HUNT: BeyondTrust agent outbound destinations (appliance discovery and rogue-destination check) // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1219, T1071.001 // CONF: low | FP: low // FALSE POSITIVES: none; this lists destinations for review // EQUIVALENCE: equivalent-with-schema-assumptions - Same discovery: outbound connections made by a process matching the BeyondTrust agent pattern, grouped by remote address and port with a distinct-host count, rarest destinations first. On an IP Connect event the acting process is src.process. // REQUIRES: SentinelOne IP Connect telemetry with the acting process name; agent pattern validated with Q1 // TUNING: Discovery query, no indicator is asserted. Record the appliance address and port, then review every destination seen on few hosts. // LOOKBACK: 30d; set the console time picker, the published query carries no time predicate // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Connections made through a proxy show the proxy address, not the appliance. // VALIDATION LEVEL: static-reviewed event.type = 'IP Connect' and src.process.name matches '^(bomgar|beyondtrust)[-_a-z0-9.]*\\.exe$' and dst.ip.address = * | group conns=count(), hosts=estimate_distinct(agent.uuid), first_seen=min(event.time), last_seen=max(event.time) by dst.ip.address, dst.port.number | sort +hosts | limit 100
Automated validation: static-passed
5 required fields · View requirements
Required telemetry
- DeviceNetworkEvents
Required fields
Timestamp: Event timeInitiatingProcessFileName: Initiating processRemoteIP: Remote addressRemotePort: Remote portDeviceId: Device identifier
Recommended fields
ActionType: Action
Fallbacks
DeviceId→DeviceName: Changes how devices are counted: renamed devices count twice.
Readiness test
DeviceNetworkEvents | where Timestamp > ago(1d) | project Timestamp, DeviceId, InitiatingProcessFileName, ActionType, RemoteIP, RemotePort | take 5
// HUNT: BeyondTrust agent outbound destinations (appliance discovery and rogue-destination check) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1219, T1071.001 // CONF: low | FP: low // FALSE POSITIVES: none; this lists destinations for review // EQUIVALENCE: equivalent-with-schema-assumptions - Same discovery: outbound connections made by a process matching the BeyondTrust agent pattern, grouped by remote address and port with a distinct-device count, rarest destinations first. Only successful connections are listed. // REQUIRES: Defender for Endpoint network telemetry (DeviceNetworkEvents) // TUNING: Discovery query, no indicator is asserted. Record the appliance address and port, then review every destination seen on few devices. // LOOKBACK: 30d (Advanced Hunting retention is 30 days; the CQL tab uses the same 30d) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Failed connection attempts are not listed. Connections made through a proxy show the proxy address, not the appliance. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0 DeviceNetworkEvents | where Timestamp >= ago(30d) | where ActionType == "ConnectionSuccess" | where InitiatingProcessFileName matches regex @"(?i)^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$" | summarize Conns = count(), Hosts = dcount(DeviceId), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by RemoteIP, RemotePort | sort by Hosts asc | take 100
Looks for: BARECLAW is a SOCKS5 proxy that relays TCP connections between a remote client and destinations, and the operator exposed it through the appliance's reverse proxy (snapshot 01). Traffic the operator sends through it to internal hosts therefore arrives from the appliance's address, not from the operator. An ordinary Jump Client dials out to the appliance; a workstation should almost never accept an inbound connection from it. Replace the placeholder with your own appliance address(es) from Q4 before running. The unedited placeholder matches nothing. FP: The appliance legitimately connects inbound to the directory, mail and syslog servers it is integrated with (snapshot 01 lists those as the only allowed outbound destinations). Exclude those hosts by aid or LocalPort; any other host accepting a connection from the appliance deserves a look. Sensors only log inbound accepts where policy enables them: confirm with a known test connection.
Known limitations and deployment notes
- PowerQuery: Inbound connections are only recorded when the policy collects them; an empty result is not proof of absence.
- PowerQuery: Direction and peer-address semantics on inbound events are not verified on a tenant.
- PowerQuery assumes: event.network.direction takes the value INCOMING for an accepted inbound connection.
- PowerQuery assumes: On an INCOMING IP Connect event src.ip.address is the remote peer and dst.ip.address the local endpoint.
- PowerQuery assumes: The appliance address is the operator's own, not a published indicator.
- KQL – Defender XDR: Inbound events are not recorded on every sensor configuration; an empty result is not proof of absence.
- KQL – Defender XDR assumes: InboundConnectionAccepted is populated for accepted inbound connections on the tenant.
- KQL – Defender XDR assumes: The appliance address is the operator's own, not a published indicator.
// HUNT: Endpoint accepts a connection from the BeyondTrust appliance address (SOCKS5 pivot) // MITRE: T1090 | T1572 | T1021 // CONF: medium | FP: medium | COST: low | REQUIRES: NetworkReceiveAcceptIP4 with RemoteAddressIP4 (policy dependent; validate in tenant). EDIT THE PLACEHOLDER FIRST // SOURCE: Mandiant GTIG BARECLAW description (SOCKS5 over WebSocket relays TCP connections); the appliance address is YOURS, not a published indicator // FALSE POSITIVES: appliance integrations with directory, mail, syslog and ITSM servers // TUNING: exclude the integration servers by aid or by LocalPort (for example the directory and syslog ports you allow from the appliance); investigate every other host // LOOKBACK: 30d #event_simpleName=NetworkReceiveAcceptIP4 | in(field="RemoteAddressIP4", values=["REPLACE_WITH_APPLIANCE_IP"]) | table([@timestamp, ComputerName, LocalAddressIP4, LocalPort, RemoteAddressIP4, RemotePort, aid], limit=500)
4 required fields · View requirements
Required telemetry
- IP Connect
Required fields
event.time: Event timeevent.network.direction: Connection directionsrc.ip.address: Peer addressdst.port.number: Local port
Recommended fields
dst.ip.address: Local address
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'IP Connect' event.network.direction = 'INCOMING' | limit 5 | columns event.time, event.network.direction, src.ip.address, dst.port.number
// HUNT: Endpoint accepts a connection from the BeyondTrust appliance address (SOCKS5 pivot)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1090, T1572, T1021
// CONF: medium | FP: medium
// FALSE POSITIVES: appliance integrations with directory, mail, syslog and ITSM servers
// EQUIVALENCE: approximate-analytic - The CQL reads the sensor's accepted-inbound-connection event. SentinelOne has no event of that name, so this reads IP Connect events whose direction is INCOMING and whose source address is the appliance address. The direction field is documented but not attested in shipped queries.
// REQUIRES: SentinelOne IP Connect telemetry with inbound direction (policy dependent; validate in the tenant). Replace REPLACE_WITH_APPLIANCE_IP with the appliance address before running
// TUNING: Exclude the integration servers by agent.uuid or by dst.port.number (for example the directory and syslog ports you allow from the appliance); investigate every other host.
// LOOKBACK: 30d; set the console time picker, the published query carries no time predicate
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Inbound connections are only recorded when the policy collects them; an empty result is not proof of absence. Direction and peer-address semantics on inbound events are not verified on a tenant.
// VALIDATION LEVEL: static-reviewed
event.type = 'IP Connect' and event.network.direction = 'INCOMING' and src.ip.address in ('REPLACE_WITH_APPLIANCE_IP')
| columns event.time, endpoint.name, dst.ip.address, dst.port.number, src.ip.address, src.port.number, src.process.name, agent.uuid
| sort -event.time
| limit 500Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceNetworkEvents
Required fields
Timestamp: Event timeActionType: ActionRemoteIP: Remote addressLocalPort: Local port
Recommended fields
LocalIP: Local address
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceNetworkEvents | where Timestamp > ago(1d) | where ActionType == "InboundConnectionAccepted" | project Timestamp, ActionType, RemoteIP, LocalPort | take 5
// HUNT: Endpoint accepts a connection from the BeyondTrust appliance address (SOCKS5 pivot)
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1090, T1572, T1021
// CONF: medium | FP: medium
// FALSE POSITIVES: appliance integrations with directory, mail, syslog and ITSM servers
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: an accepted inbound connection whose remote address is the appliance address, read from DeviceNetworkEvents InboundConnectionAccepted.
// REQUIRES: Defender for Endpoint network telemetry (DeviceNetworkEvents) with inbound events (policy dependent; validate in the tenant). Replace REPLACE_WITH_APPLIANCE_IP with the appliance address before running
// TUNING: Exclude the integration servers by DeviceId or by LocalPort (for example the directory and syslog ports you allow from the appliance); investigate every other device.
// LOOKBACK: 30d (Advanced Hunting retention is 30 days; the CQL tab uses the same 30d)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Inbound events are not recorded on every sensor configuration; an empty result is not proof of absence.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceNetworkEvents
| where Timestamp >= ago(30d)
| where ActionType == "InboundConnectionAccepted"
| where RemoteIP in ("REPLACE_WITH_APPLIANCE_IP")
| project Timestamp, ReportId, DeviceId, DeviceName, LocalIP, LocalPort, RemoteIP, RemotePort, InitiatingProcessFileName
| sort by Timestamp desc
| take 500Looks for: A successful logon of type 3 (network) or 10 (remote interactive) whose source address is the appliance. This is the credential-use half of the SOCKS5 pivot: the operator reached the vault with bt-secrets and the appliance brokers credentials for downstream systems (snapshot 01), so stolen credentials replayed through the tunnel arrive from the appliance's address. Replace the placeholder first. FP: Service accounts that the appliance itself uses for directory lookups or integrations will log on from the appliance address. Exclude those UserName values after confirming each one has a named owner.
Known limitations and deployment notes
- PowerQuery: A cached or unlock logon type (CACHED_REMOTE_INTERACTIVE) is not included, as in the CQL.
- PowerQuery: If src.endpoint.ip.address is not populated on the tenant the query returns nothing.
- PowerQuery assumes: src.endpoint.ip.address holds the source address of a network logon; the field is documented but unverified here.
- PowerQuery assumes: The appliance address is the operator's own, not a published indicator.
- KQL – Defender XDR: RemoteIP is empty on some logons, which the predicate cannot match.
- KQL – Defender XDR assumes: RemoteIP holds the source address of the logon.
// HUNT: Network or remote-interactive logon sourced from the BeyondTrust appliance address // MITRE: T1078 | T1021 | T1090 // CONF: medium | FP: medium | COST: low | REQUIRES: UserLogon with RemoteAddressIP4 and LogonType. EDIT THE PLACEHOLDER FIRST // SOURCE: Mandiant GTIG (credential vault access and SOCKS5 tunnel); the appliance address is YOURS, not a published indicator // FALSE POSITIVES: appliance service accounts used for directory lookups and integrations // TUNING: exclude the appliance's own integration UserName values once each has a named owner; investigate every other account // LOOKBACK: 30d #event_simpleName=UserLogon | LogonType=/^(3|10)$/ | in(field="RemoteAddressIP4", values=["REPLACE_WITH_APPLIANCE_IP"]) | table([@timestamp, ComputerName, UserName, LogonType, RemoteAddressIP4, aid], limit=500)
4 required fields · View requirements
Required telemetry
- Login
Required fields
event.time: Event timeevent.login.type: Logon typeevent.login.loginIsSuccessful: Logon successsrc.endpoint.ip.address: Source address
Recommended fields
event.login.userName: Account
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Login' src.endpoint.ip.address = * | limit 5 | columns event.time, event.login.type, event.login.loginIsSuccessful, src.endpoint.ip.address
// HUNT: Network or remote-interactive logon sourced from the BeyondTrust appliance address
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1078, T1021, T1090
// CONF: medium | FP: medium
// FALSE POSITIVES: appliance service accounts used for directory lookups and integrations
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a successful network or remote-interactive logon whose source address is the appliance address. CQL logon types 3 and 10 map to NETWORK and REMOTE_INTERACTIVE. The source address field is documented but not attested in shipped queries.
// REQUIRES: SentinelOne Login telemetry with the source endpoint address. Replace REPLACE_WITH_APPLIANCE_IP with the appliance address before running
// TUNING: Exclude the appliance's own integration account names once each has a named owner; investigate every other account.
// LOOKBACK: 30d; set the console time picker, the published query carries no time predicate
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A cached or unlock logon type (CACHED_REMOTE_INTERACTIVE) is not included, as in the CQL. If src.endpoint.ip.address is not populated on the tenant the query returns nothing.
// VALIDATION LEVEL: static-reviewed
event.type = 'Login' and event.login.type in ('NETWORK', 'REMOTE_INTERACTIVE') and event.login.loginIsSuccessful = true and src.endpoint.ip.address in ('REPLACE_WITH_APPLIANCE_IP')
| columns event.time, endpoint.name, event.login.userName, event.login.type, src.endpoint.ip.address, agent.uuid
| sort -event.time
| limit 500Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceLogonEvents
Required fields
Timestamp: Event timeActionType: ActionLogonType: Logon typeRemoteIP: Source address
Recommended fields
AccountName: Account
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceLogonEvents | where Timestamp > ago(1d) | project Timestamp, ActionType, LogonType, RemoteIP | take 5
// HUNT: Network or remote-interactive logon sourced from the BeyondTrust appliance address
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1078, T1021, T1090
// CONF: medium | FP: medium
// FALSE POSITIVES: appliance service accounts used for directory lookups and integrations
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a successful network or remote-interactive logon whose source address is the appliance address. CQL logon types 3 and 10 map to Network and RemoteInteractive.
// REQUIRES: Defender for Endpoint logon telemetry (DeviceLogonEvents). Replace REPLACE_WITH_APPLIANCE_IP with the appliance address before running
// TUNING: Exclude the appliance's own integration account names once each has a named owner; investigate every other account.
// LOOKBACK: 30d (Advanced Hunting retention is 30 days; the CQL tab uses the same 30d)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: RemoteIP is empty on some logons, which the predicate cannot match.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceLogonEvents
| where Timestamp >= ago(30d)
| where ActionType == "LogonSuccess"
| where LogonType in~ ("Network", "RemoteInteractive")
| where RemoteIP in ("REPLACE_WITH_APPLIANCE_IP")
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, LogonType, RemoteIP
| sort by Timestamp desc
| take 500Looks for: PE files, new executables and archives created on an endpoint by the agent process itself. This behavior was not reported in the ARMORY CASTLE intrusion: the sources describe documents being downloaded from endpoints, which the sensor does not log as a file event. It is included as general coverage of remote-support abuse and labelled as such. Reads and downloads through the file-transfer service are a coverage gap (see section 15). FP: Help desk software pushes (installers, patches, scripts) delivered through a session create exactly these files. Exclude your sanctioned deployment paths by TargetFileName and reconcile the rest with the session report.
Known limitations and deployment notes
- PowerQuery: A payload written with a non-listed extension is not captured.
- PowerQuery: Writes to an existing file (File Modification) are not included.
- PowerQuery assumes: The extension list (exe, dll, sys, scr, msi, zip, 7z, rar) stands in for the CQL's executable and archive event types.
- PowerQuery assumes: tgt.file.sha256 is populated for created files on the tenant.
- KQL – Defender XDR: A payload written with a non-listed extension is not captured.
- KQL – Defender XDR: Writes to an existing file (FileModified) are not included.
- KQL – Defender XDR assumes: The extension list (exe, dll, sys, scr, msi, zip, 7z, rar) stands in for the CQL's executable and archive event types.
- KQL – Defender XDR assumes: SHA256 is often unpopulated in DeviceFileEvents; SHA1 is the safer pivot.
// HUNT: Executable or archive written by the BeyondTrust agent process // MITRE: T1219 | T1105 | T1570 // CONF: low | FP: medium | COST: low | REQUIRES: PeFileWritten, NewExecutableWritten, ZipFileWritten with ContextBaseFileName; agent pattern validated with Q1 // SOURCE: general remote-support abuse coverage; NOT observed in the ARMORY CASTLE reporting (snapshot 01 describes downloads FROM endpoints) // FALSE POSITIVES: help desk software pushes and scripted fixes delivered through a session // TUNING: exclude sanctioned deployment folders by TargetFileName and reconcile remaining hits with the appliance session report // LOOKBACK: 7d #event_simpleName=/^(PeFileWritten|NewExecutableWritten|ZipFileWritten)$/ | ContextBaseFileName=/^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$/i | table([@timestamp, ComputerName, #event_simpleName, ContextBaseFileName, TargetFileName, SHA256HashData, aid], limit=500)
3 required fields · View requirements
Required telemetry
- File Creation
Required fields
event.time: Event timesrc.process.name: Writing process nametgt.file.path: Written file path
Recommended fields
endpoint.name: Host name
Optional fields
tgt.file.sha256: Hash. Population varies by tenant; confirm with the readiness test.
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'File Creation' tgt.file.path = * | limit 5 | columns event.time, src.process.name, tgt.file.path
// HUNT: Executable or archive written by the BeyondTrust agent process // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1219, T1105, T1570 // CONF: low | FP: medium // FALSE POSITIVES: help desk software pushes and scripted fixes delivered through a session // EQUIVALENCE: approximate-analytic - The CQL reads the sensor's content-based executable and archive write events. SentinelOne has no content-typed file event, so this reads File Creation events by the BeyondTrust agent process and selects executable and archive files by extension. A renamed payload is missed and a non-PE file with an executable extension is included. On a File Creation event the acting process is src.process. // REQUIRES: SentinelOne File Creation telemetry with the writing process name and file path; agent pattern validated with Q1 // TUNING: Exclude sanctioned deployment folders by tgt.file.path and reconcile remaining hits with the appliance session report. // LOOKBACK: 7d; set the console time picker, the published query carries no time predicate // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A payload written with a non-listed extension is not captured. Writes to an existing file (File Modification) are not included. // VALIDATION LEVEL: static-reviewed event.type = 'File Creation' and src.process.name matches '^(bomgar|beyondtrust)[-_a-z0-9.]*\\.exe$' and tgt.file.path matches '\\.(exe|dll|sys|scr|msi|zip|7z|rar)$' | columns event.time, endpoint.name, src.process.name, tgt.file.path, tgt.file.sha256, agent.uuid | sort -event.time | limit 500
Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceFileEvents
Required fields
Timestamp: Event timeActionType: ActionInitiatingProcessFileName: Writing processFileName: Written file name
Recommended fields
FolderPath: Written file path
Optional fields
SHA1: Hash. SHA256 is often unpopulated in DeviceFileEvents; SHA1 is the safer pivot.
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceFileEvents | where Timestamp > ago(1d) | project Timestamp, ActionType, InitiatingProcessFileName, FileName | take 5
// HUNT: Executable or archive written by the BeyondTrust agent process
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1219, T1105, T1570
// CONF: low | FP: medium
// FALSE POSITIVES: help desk software pushes and scripted fixes delivered through a session
// EQUIVALENCE: approximate-analytic - The CQL reads the sensor's content-based executable and archive write events. Defender has no content-typed file event, so this reads file creation and rename events by the BeyondTrust agent process and selects executable and archive files by extension. A renamed payload is missed.
// REQUIRES: Defender for Endpoint file telemetry (DeviceFileEvents); agent pattern validated with Q1
// TUNING: Exclude sanctioned deployment folders by FolderPath and reconcile remaining hits with the appliance session report.
// LOOKBACK: 7d; extend to 30d for the incident window
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A payload written with a non-listed extension is not captured. Writes to an existing file (FileModified) are not included.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceFileEvents
| where Timestamp >= ago(7d)
| where ActionType in ("FileCreated", "FileRenamed")
| where InitiatingProcessFileName matches regex @"(?i)^(bomgar|beyondtrust)[-_a-z0-9.]*\.exe$"
| where FileName matches regex @"(?i)\.(exe|dll|sys|scr|msi|zip|7z|rar)$"
| project Timestamp, ReportId, DeviceId, DeviceName, InitiatingProcessFileName, FolderPath, FileName, SHA1, SHA256
| sort by Timestamp desc
| take 500Looks for: The two published SHA-256 values, the published tool and file names, and the distinctive command-line tokens (uidchanarge, zz-root-persist, bt-secrets, bt-sysconfig) on any Falcon-sensored host, Windows or Linux. Expect zero: SAWFLY, BARECLAW and the persistence scripts live on the appliance, which carries no Falcon sensor. The query catches the case where a sample was copied to a sensored host (analyst workstation, malware sandbox, staging server) and any lookalike that reuses the names. It is not evidence the appliance is clean.
Known limitations and deployment notes
- PowerQuery: The indicators are appliance-resident, so a clean result on a sensored estate is the expected outcome and does not clear the appliance.
- PowerQuery assumes: tgt.process.image.sha256 is populated for created processes on the tenant.
- PowerQuery assumes: src.process.user holds the account of the creating process.
- KQL – Defender XDR: Advanced Hunting keeps 30 days, so the CQL's 90d window is shortened to 30d here; the CQL tab covers 90d.
- KQL – Defender XDR: The indicators are appliance-resident, so a clean result on a sensored estate is the expected outcome and does not clear the appliance.
- KQL – Defender XDR assumes: SHA256 is populated for the created process; Microsoft marks it usually not populated, so the name and command-line arms carry the hunt where it is empty.
// HUNT: Published ARMORY CASTLE hashes, tool names and command-line tokens on any sensored host // MITRE: T1505.003 | T1090 | T1548.001 | T1070.004 // CONF: high | FP: low | COST: medium | REQUIRES: ProcessRollup2 with SHA256HashData, FileName, CommandLine // SOURCE: Mandiant GTIG File Indicators table and recovered commands (snapshot 01). Appliance-resident: expected zero on a sensored estate // FALSE POSITIVES: none expected; a sandbox or analyst host that holds a sample will hit by design // LOOKBACK: 90d #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | (SHA256HashData=/^(dc14e215269a93fdbc4c1a80b984c23faf7af0911c6dbb85309796a6f2ae95fb|1f19b9a27d79c11bda00a1e8faf74a7fdd683d38ccef1b60df2fd0307e3aa462)$/i or FileName=/^(ingredi_ws|mangoapi\.php|dbus-authd)$/i or CommandLine=/(uidchanarge|zz-root-persist|bt-secrets|bt-sysconfig)/i) | table([@timestamp, ComputerName, UserName, FileName, SHA256HashData, ParentBaseFileName, CommandLine, aid], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timetgt.process.name: Created process nametgt.process.image.sha256: Created process hashtgt.process.cmdline: Created command line
Recommended fields
src.process.name: Creator process
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Process Creation' tgt.process.image.sha256 = * | limit 5 | columns event.time, tgt.process.name, tgt.process.image.sha256, tgt.process.cmdline
// HUNT: Published ARMORY CASTLE hashes, tool names and command-line tokens on any sensored host
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1505.003, T1090, T1548.001, T1070.004
// CONF: high | FP: low
// FALSE POSITIVES: none expected; a sandbox or analyst host that holds a sample will hit by design
// EQUIVALENCE: equivalent-with-schema-assumptions - Same indicator predicate on process creation: either published SHA256, one of the three published tool names, or one of the four recovered command-line tokens. in:anycase and matches are case-insensitive, which reproduces the CQL /i intent. The created process is tgt.process on a Process Creation event.
// REQUIRES: SentinelOne process-creation telemetry with image hash, name and command line
// TUNING: None expected; treat every hit as an incident. A sandbox or analyst host that holds a sample will hit by design.
// LOOKBACK: 90d; set the console time picker, the published query carries no time predicate
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: The indicators are appliance-resident, so a clean result on a sensored estate is the expected outcome and does not clear the appliance.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' and (tgt.process.image.sha256 in:anycase ('dc14e215269a93fdbc4c1a80b984c23faf7af0911c6dbb85309796a6f2ae95fb', '1f19b9a27d79c11bda00a1e8faf74a7fdd683d38ccef1b60df2fd0307e3aa462') or tgt.process.name in:anycase ('ingredi_ws', 'mangoapi.php', 'dbus-authd') or tgt.process.cmdline matches '(uidchanarge|zz-root-persist|bt-secrets|bt-sysconfig)')
| columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.image.sha256, src.process.name, tgt.process.cmdline, agent.uuid
| sort -event.time
| limit 200Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameSHA256: Created process hashProcessCommandLine: Created command line
Recommended fields
InitiatingProcessFileName: Initiating process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, SHA256, ProcessCommandLine | take 5
// HUNT: Published ARMORY CASTLE hashes, tool names and command-line tokens on any sensored host
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1505.003, T1090, T1548.001, T1070.004
// CONF: high | FP: low
// FALSE POSITIVES: none expected; a sandbox or analyst host that holds a sample will hit by design
// EQUIVALENCE: equivalent-with-schema-assumptions - Same indicator predicate on process creation: either published SHA256, one of the three published tool names, or one of the four recovered command-line tokens. in~ and contains are case-insensitive, which reproduces the CQL /i intent. SHA256 is often unpopulated, so the hash arm may not fire on a healthy tenant.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: None expected; treat every hit as an incident. A sandbox or analyst device that holds a sample will hit by design.
// LOOKBACK: 30d (Advanced Hunting retention; the CQL tab covers 90d)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Advanced Hunting keeps 30 days, so the CQL's 90d window is shortened to 30d here; the CQL tab covers 90d. The indicators are appliance-resident, so a clean result on a sensored estate is the expected outcome and does not clear the appliance.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceProcessEvents
| where Timestamp >= ago(30d)
| where SHA256 in~ ("dc14e215269a93fdbc4c1a80b984c23faf7af0911c6dbb85309796a6f2ae95fb", "1f19b9a27d79c11bda00a1e8faf74a7fdd683d38ccef1b60df2fd0307e3aa462") or FileName in~ ("ingredi_ws", "mangoapi.php", "dbus-authd") or ProcessCommandLine contains "uidchanarge" or ProcessCommandLine contains "zz-root-persist" or ProcessCommandLine contains "bt-secrets" or ProcessCommandLine contains "bt-sysconfig"
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, SHA256, InitiatingProcessFileName, ProcessCommandLine
| sort by Timestamp desc
| take 200Detection Rules by Platform
CrowdStrike: Custom IOA
| IOA name | Field Patterns | Benign Exclusions | Deployment Path |
|---|---|---|---|
| Endpoint accepts a connection from the appliance. Promote Q5 | Platform Windows; rule type Network Connection; remote IP address = your appliance address(es) (from Q4); inbound direction where the rule type offers it | The directory, mail, syslog and ITSM servers the appliance is integrated with, by host | Endpoint Security → Custom IOA → Network Connection (Detect only. Confirm in a lab that your IOA type evaluates inbound accepts before relying on it; otherwise keep Q5 as a scheduled search) |
| Published ARMORY CASTLE tools and tokens on any host. Promote Q8 | Platform Windows and Linux; rule type Process Creation; image file name regex (ingredi_ws|mangoapi\.php|dbus-authd); command line regex uidchanarge|zz-root-persist|bt-secrets|bt-sysconfig | None expected. Allow-list a malware analysis host by aid if it holds samples on purpose | Custom IOA → Process Creation (Detect). The two SHA-256 values go in IOC Management as detect, not in this IOA |
SentinelOne: custom detection rules
| Rule | Source query | Run as | Notes |
|---|---|---|---|
| Published ARMORY CASTLE tools and tokens on any host. Promote Q8 | Q8, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device" |
Create the rule with POST /web/api/v2.1/cloud-detection/rules, queryType: "scheduled" and queryLang: "2.0", with the query in data.scheduledParams.query. Use 2.0 operator spellings: a rule written with the 1.0 token ContainsCIS was accepted and never fired on a tenant. The API does not warn, so lint the body before deploying.
Microsoft Defender: custom detection rules
| Rule | Source query | Run as | Notes |
|---|---|---|---|
| Published ARMORY CASTLE tools and tokens on any host. Promote Q8 | Q8, KQL – Defender XDR tab | Custom detection rule, alert only, every hour | The query returns Timestamp, ReportId and DeviceId, which Microsoft recommends for Defender for Endpoint tables so alerts carry the device group scope and the process tree. Remove the Timestamp filter and the final sort and take before saving the rule: the service applies the rule's lookback itself |
Q1, Q2, Q3, Q6 and Q7 stay a hunt in this pack, not a rule. A rule can generate only 150 alerts per run. Continuous (NRT) frequency needs a single table and no comment lines, so delete the generated comment header from the query first.
Machine-Readable IOC Appendix
Grouped IOC Quick-Copy
Two importable atomics (the SAWFLY and BARECLAW SHA-256 values), both detect, none prevent: each appears in one source only. Neither is likely to match a Windows endpoint, because both files live on the appliance. File names, paths, URL paths and command strings are hunt values and cannot be imported as Falcon IOCs.
type,value,action,severity,expiration,description,tags sha256,dc14e215269a93fdbc4c1a80b984c23faf7af0911c6dbb85309796a6f2ae95fb,detect,high,2027-04-17,SAWFLY obfuscated PHP webshell mangoapi.php from the ARMORY CASTLE BeyondTrust intrusion (Mandiant GTIG 2026-10-15; single source; appliance-resident),campaign:ARMORY-CASTLE sha256,1f19b9a27d79c11bda00a1e8faf74a7fdd683d38ccef1b60df2fd0307e3aa462,detect,high,2027-04-17,BARECLAW SOCKS5 WebSocket tunneler ingredi_ws from the ARMORY CASTLE BeyondTrust intrusion (Mandiant GTIG 2026-10-15; single source; appliance-resident),campaign:ARMORY-CASTLE
indicatorType,indicatorValue,action,title,description,expirationTime,severity,recommendedActions,rbacGroups,category,mitretechniques,GenerateAlert FileSha256,dc14e215269a93fdbc4c1a80b984c23faf7af0911c6dbb85309796a6f2ae95fb,Audit,SAWFLY obfuscated PHP webshell mangoapi.php from the ARMORY ,SAWFLY obfuscated PHP webshell mangoapi.php from the ARMORY CASTLE BeyondTrust intrusion (Mandiant GTIG 2026-10-15; single source; appliance-resident),2027-04-17T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,1f19b9a27d79c11bda00a1e8faf74a7fdd683d38ccef1b60df2fd0307e3aa462,Audit,BARECLAW SOCKS5 WebSocket tunneler ingredi_ws from the ARMOR,BARECLAW SOCKS5 WebSocket tunneler ingredi_ws from the ARMORY CASTLE BeyondTrust intrusion (Mandiant GTIG 2026-10-15; single source; appliance-resident),2027-04-17T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True
Column names and allowed values are from Microsoft's documented parameter table. Check each expirationTime before importing: an indicator whose date has passed is already expired. Download the sample CSV from the Import page to confirm the column order before a bulk import. Each file takes at most 500 indicators. Learn describes the import per entity type, so if a mixed file is rejected, split it by indicatorType. An imported indicator does nothing unless the matching Advanced features are on (for example Custom network indicators and Allow or block file).
This pack does not ship a SentinelOne import block: the import format could not be verified against SentinelOne's own documentation. Export a sample from your console and the block can be added with confidence.
# Behavioral signatures (detection logic, not IOCs). Endpoint-visible items first, appliance-only items last. BeyondTrust agent process spawns cmd, powershell, pwsh, wscript, cscript, mshta, rundll32, certutil, curl, wmic, nltest, whoami, systeminfo, ipconfig, tasklist, 7z, rar or tar (Q2) four or more distinct tools under the agent on one host in one day (Q3) endpoint accepts a connection from, or sees a type 3 or type 10 logon sourced from, the appliance address (Q5, Q6) agent process writes an executable or archive to disk (Q7, general abuse, not reported in this campaign) agent connects to a destination that is not your appliance or the vendor's cloud (Q4) # Appliance-side only (not Falcon-queryable; use forwarded syslog, proxy or WAF logs, or a disk image): syslog event user_changed with jump_item_role (default or teams) new name Administrator, old name No Access syslog event login success to web/login from residential-broadband or commercial-VPN space, or outside business hours POST to /app_84304470%2Ephp, then a new .php file about 11 minutes later under the web root POST body parameter _c94mfe; request to a path never seen before ending in .php WebSocket upgrade (HTTP 101) to /uidchanarge from a non-support address /bin/sh copied to /usr/bin/dbus-authd with root ownership and the SUID bit bt-secrets get ... vault, followed by rm of /home/bomgar/log/bt-secrets.log* new /home/bomgar/sbin/post_boot.d/zz-root-persist; NOPASSWD line appended to /ns/config/sudoers.template; bt-sysconfig --no-restart misc acl wswsws and backend webskd3 in /ns/config/haproxy.conf routing to 127.0.0.1:19800 bulk rm of /ns/log/*.log, /var/log/messages and /tmp/sshauth.*; gap in forwarded appliance syslog
# Hunt values from the Mandiant report (snapshot 01). Not importable as Falcon IOCs. All appliance-resident unless noted. # File names mangoapi.php ingredi_ws dbus-authd zz-root-persist # URL paths and parameters (proxy or WAF logs) /app_84304470%2Ephp /uidchanarge _c94mfe # Local listener (loopback on the appliance) 127.0.0.1:19800 # HAProxy strings in /ns/config/haproxy.conf acl wswsws path /uidchanarge use_backend webskd3 if wswsws backend webskd3 server websocks5srv 127.0.0.1:19800 # Appliance utilities and files that are STOCK (hunt the behavior, never block the binary) /ns/sbin/bt-secrets /ns/sbin/bt-sysconfig /ns/config/sudoers.template /ns/config/haproxy.conf # BARECLAW invocation as recovered (token redacted in the source) /tmp/ingredi_ws --listen 19800 --token <REDACTED> --obfs -q --ws-path /uidchanarge
# Patch / exposure audit (the fix) # Affected: every Remote Support release up to and including 26.2.3. # Fix: BT26-05-RS patch for releases 24.3.1 through 26.2.3. Older than 24.3.1: upgrade to a supported version first, then patch. # SaaS: vendor patched all tenants on 2026-10-09; the credential and configuration review still applies. # Self-hosted: apply the patch from the /appliance interface, or confirm it applied automatically if the appliance takes automatic updates. # If the patch is not visible in /appliance, open a case with BeyondTrust Support referencing BT26-05. # Upgrading or patching closes the flaw; it does NOT remediate prior exposure. Treat an appliance that was internet-reachable on a # vulnerable version since 2026-08-29 as potentially compromised until reviewed (Mandiant, CISA). # Order of operations: preserve (snapshot with memory, export disk) -> isolate at the perimeter -> rebuild or patch -> THEN rotate credentials. # Restrict /login and /appliance by IP or segment; only the representative console, customer portal and Jump Client traffic should be internet-reachable.
Detection Validation Gates
| Gate | Check | Pass Criteria |
|---|---|---|
| Telemetry ready | Confirm the sensor is on the endpoints that run a BeyondTrust agent. Confirm process creation with parent and command line (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents) and outbound connections (CrowdStrike: NetworkConnectIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents) are populated. Run Q1 and confirm the agent process names; amend the pattern. Test whether inbound accepts (CrowdStrike: NetworkReceiveAcceptIP4) and logon source addresses (CrowdStrike: UserLogon) arrive, by making a known connection from a lab host | Q1 returns your agent names and host counts; ParentBaseFileName and CommandLine populated for agent children; inbound-accept and logon-source events present or recorded as a known gap |
| Appliance-side visibility | Confirm appliance syslog and session events are forwarded to a SIEM over TLS with retention covering 2026-08-29 onward, and that a reverse proxy, WAF or firewall log for the appliance address exists. Without them N1 to N4 cannot run and the exploit and webshell stages are blind | Logs present and time-synced, or the gap is recorded in the ticket and escalated to BeyondTrust Support |
| Benign baseline | Run Q2, Q3 and Q7 for 30 days on a quiet period and review with the help desk. Run Q4 and confirm every destination is your appliance or the vendor's cloud. Run Q5 and Q6 after filling the placeholder and listing the integration servers | Every Q2, Q3 and Q7 row explained by a named help desk workflow; Q4 shows only expected destinations; Q5 and Q6 show only listed integration servers and service accounts; Q8 returns zero |
| Positive test | Lab host only: from a test session, run whoami, systeminfo, ipconfig and tasklist in the console command shell; make one inbound TCP connection to the lab host from the test appliance address. Never use real malware or the live exploit | Q2 and Q3 fire with the agent as parent; Q5 fires if inbound-accept logging is on |
| Promotion | Move Q5 and Q8 to Custom IOA Detect (section 9). Keep Q2, Q3 and Q7 as scheduled investigations until the help desk exclusions are stable | No unexplained alert for 30 days; no Block mode for any rule in this pack |
Hardening: Tiered & Deployable
This is patchable, and the order matters: preserve, isolate, patch or rebuild, then rotate. Platforms touched: the vendor appliance and its administrative plane, the perimeter and network path around it, Windows endpoints that run the agent, identity (appliance administrators and brokered credentials), and logging. Each control cites a MITRE mitigation plus an authority; where no formal benchmark exists for this product the control is flagged.
- Apply BT26-05-RS, or upgrade first if older than 24.3.1 (M1051 Update Software; BeyondTrust BT26-05 as relayed by CISA and Mandiant; NIST SP 800-53 SI-2 Flaw Remediation). SaaS tenants were patched by the vendor on 2026-10-09. Check: the patch is visible and applied in /appliance; if not visible, open a case referencing BT26-05. Patching does not undo prior compromise.
- Treat any appliance that was internet-reachable on a vulnerable version since 2026-08-29 as potentially compromised (Mandiant, CISA). Preserve (snapshot a virtual appliance with memory and export the disk; request preservation from BeyondTrust Support for hardware and SaaS), isolate at the perimeter firewall rather than in /appliance so the configuration stays intact, then rebuild rather than clean, because host-level persistence survives reboot and configuration reset (M1030 Network Segmentation; CISA KEV "forensic triage: Yes").
- Restrict /login and /appliance to trusted networks (M1035 Limit Access to Resource Over Network; Mandiant Option 3 Part A; CISA; BeyondTrust B Series on-premises security guide). Only the representative console, customer portal and Jump Client traffic should be reachable from the internet. Check: from an untrusted network, /appliance and /login admin paths do not respond.
- Review the /login configuration against a pre-2026-08-29 baseline (M1026 Privileged Account Management; Mandiant). Look for Jump Item or Team roles raised to Administrator, new users, API accounts and security providers, changed group or session policies, and outbound event or syslog destinations. Remove anything with no change record or named owner. Review support session reports, including file transfers, for the window.
- Rotate credentials only after patch or rebuild, in dependency order (M1027 Password Policies; NIST SP 800-53 IA-5; CISA: rotate every credential the appliance stored or injected). See Playbook D. Rotating earlier hands the new secrets to an attacker who still controls the appliance.
- Require SAML single sign-on with phishing-resistant MFA for all /login users, remove local accounts except one vaulted break-glass account with alerting on use, and enable MFA on the built-in Admin account (M1032 Multi-factor Authentication; BeyondTrust Two-Factor Authentication Guidelines as cited by Mandiant; NIST SP 800-53 IA-2(1)). Check: the identity provider shows SSO enforced and the local-account list shows one entry.
- Default-deny outbound filtering from the appliance, allowing only BeyondTrust update and licensing endpoints and your own syslog and directory servers (M1037 Filter Network Traffic; Mandiant Option 3 Part C). This breaks the tunnel's reach into the internal network. Check: Q5 and Q6 return only the listed integration servers. See Playbook B for the endpoint-side companion rule. ⚠ best-practice, no formal benchmark for this product
- Put a reverse proxy or WAF with full URI logging in front of the appliance (M1047 Audit; Mandiant Part A). It keeps a record of request paths the appliance cannot alter and is the only place the staging path, the SAWFLY parameter and the tunnel path can show up. Check: N3 returns data. See Playbook C.
- Forward appliance syslog and session events to the SIEM over TLS with multi-month retention and alert on forwarding gaps (M1047 Audit; CISA; CIS Controls v8 Control 8). Check: N4 shows continuous hourly counts.
- Set the default Jump Item role in every group policy to No Access, grant roles through policy rather than per user, and scope API accounts to the minimum permission set with a named owner (M1018 User Account Management; NIST SP 800-53 AC-6 Least Privilege; Mandiant Part C). Check: N1 shows no unplanned elevation.
- Block inbound connections from the appliance address on workstations with host firewall policy (M1037). Agents dial out; a workstation has no business accepting a connection from the appliance. Pilot on one ring: servers integrated with the appliance need exceptions. See Playbook B. ⚠ best-practice, derived from the sourced egress recommendation
- Keep privileged credentials out of the Remote Support Vault. Use Password Safe or an external vault with credential injection and store only non-interactive service-account credentials on the appliance (M1026; Mandiant Part C). The operator emptied the appliance's vault; what is not stored cannot be dumped.
- Subscribe self-hosted appliances to automatic updates, and track vendor advisories for edge devices (M1051; CISA BOD 26-04 prioritization guidance). GTIG assesses ARMORY CASTLE will keep using edge-device zero-days and warns of broad exploitation after disclosure, as seen after CVE-2023-46805 and CVE-2024-21887.
- Extend sensor coverage to the systems the appliance can reach, and make an agent-name and appliance-address baseline a standing control (M1047). The appliance itself will stay unsensored, so Q1 and Q4 output should be reviewed whenever Jump Clients are redeployed. ⚠ best-practice, no formal benchmark
- Evaluate whether an internet-facing self-hosted remote-support appliance is required (M1042 Disable or Remove Feature). The SaaS tenants were patched by the vendor on 2026-10-09, so a hosted deployment shortens patch latency; this is a risk trade-off to weigh, not a finding of the sources.
Deployable Playbooks
Playbook A · Agent inventory on a Windows endpoint (read-only)
# Playbook A. Inventory BeyondTrust agents on a Windows endpoint (read-only)
# Prerequisites: local admin or an endpoint management shell. Works on Windows PowerShell 5.1 and 7.
# Reboot required: no
# Rollback: none required (read-only)
Get-CimInstance Win32_Service |
Where-Object { $_.PathName -match 'bomgar|beyondtrust' -or $_.DisplayName -match 'bomgar|beyondtrust|jump client' } |
Select-Object Name, DisplayName, State, StartMode, StartName, PathName
Get-Process | Where-Object { $_.ProcessName -match '^(bomgar|beyondtrust)' } |
Select-Object ProcessName, Id, Path, StartTime
# Compare the names you see with the pattern in Q1 to Q4 and Q7; amend the queries if they differ.
Playbook B · Block inbound from the appliance on workstations (host firewall, pilot first)
# Playbook B. Block inbound connections from the appliance address on workstations (host firewall, pilot ring first)
# Prerequisites: the appliance address(es) from Q4. A list of servers integrated with the appliance (directory, mail, syslog, ITSM)
# that must NOT receive this rule. Apply by GPO or MDM to a pilot workstation ring only.
# Reboot required: no
# Rollback: Remove-NetFirewallRule -DisplayName 'HuntPack BT block inbound from appliance'
$Appliance = @('REPLACE_WITH_APPLIANCE_IP') # one or more addresses
New-NetFirewallRule -DisplayName 'HuntPack BT block inbound from appliance' `
-Direction Inbound -Action Block -Profile Any -RemoteAddress $Appliance
# Verify: Get-NetFirewallRule -DisplayName 'HuntPack BT block inbound from appliance' | Get-NetFirewallAddressFilter
# Verify behavior: Q5 should stop showing accepts on pilot hosts; the agent (outbound) must keep working.
Playbook C · Reverse proxy logging and published-path marker (nginx)
# Playbook C. Reverse proxy in front of the appliance: log full URIs and the upgrade header, mark the published tunnel and staging paths
# Prerequisites: a reverse proxy (nginx shown) you control in front of the appliance; a change window. Detect-and-log first.
# Blocking the published paths is cheap but low value: the operator chose them and can change them.
# Reboot required: no (reload nginx)
# Rollback: remove the snippet and run: nginx -t && systemctl reload nginx
# http context:
log_format bt_audit '$remote_addr [$time_iso8601] "$request_method $request_uri" $status "$http_upgrade" "$http_user_agent"';
access_log /var/log/nginx/bt_audit.log bt_audit;
map $request_uri $bt_published_path {
default 0;
~*app_84304470(%2e|\.)php 1;
~*uidchanarge 1;
}
# Inside the server block, after you have confirmed no legitimate traffic uses these paths:
# if ($bt_published_path) { return 404; }
# Verify: nginx -t ; then request a harmless unknown path and confirm it appears in bt_audit.log with the full URI.
Playbook D · Credential rotation in dependency order
# Playbook D. Credential rotation in dependency order (run ONLY after the appliance is patched or rebuilt) # Prerequisites: a patched or rebuilt appliance; a coordinated window with help desk and vendor-support stakeholders (sessions will drop). # Order is from Mandiant Option 3 Part B (snapshot 01). # Reboot required: no # Rollback: not applicable to a rotation. Keep the previous secrets only until dependent integrations are confirmed working, then destroy them. # 1. End all active support sessions. Redeploy Jump Clients, Jumpoints and the representative console from the patched or rebuilt # appliance to invalidate existing tokens. # 2. Rotate, in this order: # a. /appliance administrative credentials # b. /login administrators and local users # c. API client secrets # d. security provider bind accounts and SAML signing keys # e. Remote Support Vault and integrated Password Safe or Privileged Remote Access credentials (rotate at the target system) # f. integration credentials: SMTP, syslog, ITSM connectors, outbound event secrets # g. any credential typed into a support session during the exposure window # 3. Review new MFA registrations on privileged accounts (CISA). # 4. Re-run Q4 to confirm agents reconnect only to the rebuilt appliance, and N1 to confirm no role elevation remains.
Playbook E · Post-fix verification
# Playbook E. Post-fix verification with the pack queries # Prerequisites: sensors on the endpoints in scope; Q1 amended with your real agent names; the appliance address in Q5 and Q6. # Reboot required: no # Rollback: none required (read-only verification) # After the rebuild or patch and the rotation: # Q4 every agent connects only to the rebuilt appliance or the vendor's cloud; no old appliance address remains. # Q5, Q6 zero rows apart from listed integration servers and service accounts. # Q2, Q3 reconcile each row against the new session reports; none from before-window accounts that were removed. # Q8 zero rows. # Re-run N1 and N2 on the new appliance's syslog daily for 30 days.
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Block inbound traffic to the appliance's public address at the perimeter firewall, not in /appliance, so the configuration stays intact for review. Deny the appliance's outbound traffic except to BeyondTrust update and licensing endpoints, and log every denied connection. On any endpoint with a confirmed Q2, Q3, Q5, Q6 or Q8 hit, network-contain the host in Falcon. Coordinate with the help desk first: isolation interrupts support operations | Network / SOC / IR | Firewall change record, containment timestamps, host and sensor IDs |
| Isolate: by platform | CrowdStrike: network-contain the host. SentinelOne: network quarantine (Disconnect from Network; confirm the label in your console version). Microsoft Defender: Isolate device (full network isolation). | Network / SOC / IR | Firewall change record, containment timestamps, host and sensor IDs |
| Preserve | Snapshot a virtual appliance with memory and export the disk before any change or reboot; for hardware and SaaS, request forensic preservation through BeyondTrust Support. Collect appliance syslog, proxy or WAF and perimeter firewall logs for the whole exposure window from 2026-08-29, because the actor deleted on-appliance logs. Export session, team-activity and user-audit reports | IR / Network | Evidence bundle with hashes and chain of custody |
| Terminate access paths | End active support sessions and disable (do not delete) new sessions, Jump Clients, Jumpoints and API accounts from /login so the audit trail survives | Appliance admin | Disable timestamps, audit export |
| Scope downstream | From the session reports (N5), list every endpoint reached in the window and every file-transfer event. Run Q2, Q3, Q5, Q6 and Q7 on those endpoints; run Q8 fleet-wide. Treat credentials and documents on every touched endpoint as exposed. Review N1 and N2 for role elevation and unexplained admin logins | IR / Threat hunting | Per-endpoint verdict table; list of files transferred |
| Eradicate | Redeploy appliances with confirmed or unknown compromise status from a clean, fully patched image; restore only a configuration backup dated before the window, or restore the newest backup while isolated and complete the review in section 12 before reconnecting anything. Issue a new TLS certificate. Redeploy Jump Clients, Jumpoints and the console from the rebuilt appliance | Appliance admin / Sysadmin | Rebuild record, new certificate, patch level confirmed |
| Recover | Rotate credentials in dependency order (Playbook D) after the rebuild. Review new MFA registrations on privileged accounts. Re-run Q4, Q5, Q6 and N1 to confirm clean state | Identity / Sysadmin | Rotation tickets with dates; verification query output |
| Improve | Enforce SAML SSO with phishing-resistant MFA, default Jump Item role No Access, default-deny appliance egress, reverse proxy with URI logging, syslog over TLS with gap alerting; promote Q5 and Q8 to Custom IOA Detect | Security engineering | Change records |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | CrowdStrike coverage | SentinelOne | Defender XDR |
|---|---|---|---|---|---|---|
| T1190 | Zero-day exploitation of the appliance | n/a (N3) | n/a | GAP appliance and web tier. No sensor on the appliance; outside endpoint telemetry. Proxy or WAF logs (N3) if they exist, otherwise vendor-side review (N6) | GAP | GAP |
| T1505.003 / T1027 | SAWFLY webshell and staging POST path | Q8 | IOA-2 | GAP on the appliance. Q8 catches only a copy on a sensored host. N3 and N6 are the checks | GAP: same limit as CrowdStrike | GAP: same limit as CrowdStrike |
| T1548.001 / T1548.003 / T1037 | SUID dbus-authd, NOPASSWD sudoers template line, zz-root-persist | Q8 | IOA-2 | GAP appliance-resident. Visible only on a disk image (N6) | GAP: same limit as CrowdStrike | GAP: same limit as CrowdStrike |
| T1555 | Vault dump with bt-secrets | Q6 | n/a | Partial the dump itself is invisible; replay of the stolen credentials against endpoints is visible only if the logon source is the appliance | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| T1070.004 | Bulk deletion of appliance logs | n/a (N4) | n/a | GAP appliance logs are gone by design; only forwarded syslog gaps (N4) reveal it | GAP | GAP |
| T1090 / T1572 | BARECLAW SOCKS5 tunnel behind HAProxy | Q5, Q6 | IOA-1 | Partial the tunnel is invisible; endpoint accepts and logons from the appliance address are visible only when inbound-accept logging is on and the appliance address is known (Q4). N3 sees the WebSocket path if proxy logs exist | Partial: Q5 approximate | Partial: same limit as CrowdStrike |
| T1078 / T1098 | Administrator login and Jump Item or Team role elevation | n/a (N1, N2) | n/a | GAP appliance syslog only; outside endpoint telemetry | GAP | GAP |
| T1219 | Remote support session reaching an internal endpoint | Q1, Q2, Q3, Q4 | n/a | Partial agent process, children and destinations are visible; the operator identity is not. Agent names must be validated (Q1). FP from normal help desk work | Partial: Q3 approximate | Partial: same limit as CrowdStrike |
| T1059 / T1082 / T1083 | Recon commands run inside the session | Q2, Q3 | n/a | Partial visible as agent children when run through a shell; file browsing inside the support UI leaves no process | Partial: Q3 approximate | Partial: same limit as CrowdStrike |
| T1005 / T1041 | File-transfer download of documents from user desktops | Q7 | n/a | GAP file reads and transferred bytes are not recorded by endpoint telemetry. N5 session reports are the only record of which files left | GAP: same limit as CrowdStrike | GAP: same limit as CrowdStrike |
| T1105 | Tool upload through a session (not reported here) | Q7 | n/a | Partial low confidence general coverage; depends on file-write events and tuning | Partial: Q7 approximate | Partial: Q7 approximate |
Honest scope: no row is rated Good: six of the eleven are a GAP and five are Partial, because the compromised system is an unsensored appliance. The exploit, the webshell, root, the vault dump, persistence, log deletion and the tunnel's inside are covered only by logs and forensic triage, not by Falcon. Validation gates: (1) agent names confirmed with Q1 and the appliance address with Q4; (2) appliance syslog and proxy or WAF logs confirmed forwarded, or the gap recorded; (3) Q2, Q3, Q7 baselined with the help desk for 30 days and Q5, Q6 tuned with the integration-server list; (4) a lab session fires Q2 and Q3, never a real payload; (5) Q5 and Q8 promoted to Custom IOA Detect only. A clean result on every query does not show the appliance is clean.
Hunt Summary Ticket
TITLE: Hunt - BeyondTrust Remote Support CVE-2026-102764 (ARMORY CASTLE zero-day, SAWFLY webshell, BARECLAW tunneler)
SEVERITY: Critical (CVSS 4.0 9.3; unauthenticated; exploited since 2026-08-29; CISA KEV 2026-10-16, due 2026-10-19)
SCOPE: Self-hosted Remote Support up to 26.2.3 (and BeyondTrust-hosted tenants for credential and role review); Windows endpoints and servers
reachable from the appliance or running a Jump Client, Jumpoint or customer client
HYPOTHESIS: A vulnerable appliance is exploited, rooted, its vault dumped and a SOCKS5 tunnel exposed; the operator then logs in as Administrator,
raises Jump Item and Team roles, and uses remote support sessions and file transfer to take documents from internal desktops.
Attributed by Mandiant/GTIG to ARMORY CASTLE (formerly UNC5221; also WARP PANDA). The endpoint sensor sees only the downstream half.
QUERIES RUN: Q1 agent inventory (run first) | Q2 agent spawns shell or recon | Q3 session burst per host | Q4 agent destinations (find appliance address) |
Q5 inbound from appliance (IOA) | Q6 logon sourced from appliance | Q7 agent file writes | Q8 published tools and tokens (IOA) | Native N1-N6
DO FIRST: Patch (BT26-05-RS) or upgrade then patch; preserve, isolate and rebuild any appliance reachable on a vulnerable version since 2026-08-29;
review Jump Item and Team roles and file-transfer sessions (N1, N2, N5); run Q1 and Q4, then Q5, Q6, Q2, Q3 on reachable endpoints;
rotate credentials only after the rebuild (Playbook D)
FINDINGS: <pending analyst execution>
GAPS: The appliance has no sensor: exploit, webshell, root, vault dump, persistence, log deletion and the tunnel are outside endpoint telemetry
(logs and forensic triage only). File reads and file-transfer volume are not recorded. Agent process names are unverified until Q1.
Inbound-accept logging depends on sensor policy. The vendor advisory BT26-05 could not be fetched (HTTP 403).
ACTIONS: Patch and rebuild; MFA via SAML; default Jump Item role No Access; default-deny appliance egress; reverse proxy with URI logging;
syslog over TLS with gap alerts; promote Q5 and Q8 to Custom IOA Detect; no Block mode
OWNER: HuntPack
VERSION: v0.1 - 2026-10-17
Changelog
References
| Tier | Source | Used For | Access Date |
|---|---|---|---|
| 1 | Google Threat Intelligence Group / Mandiant: ARMORY CASTLE Exploits BeyondTrust | TTPs, tooling, file hashes, commands, HAProxy strings, attribution, remediation (snapshot 01) | 2026-10-17 |
| 1 | NVD record CVE-2026-102764 | Description, affected range, CVSS 4.0 and 3.1, SSVC (snapshot 02) | 2026-10-17 |
| 1 | CISA: Urges Patching Critical Vulnerability in BeyondTrust Remote Support | Active exploitation, patch and isolation guidance (snapshot 03) | 2026-10-17 |
| 1 | CISA Known Exploited Vulnerabilities catalog entry | KEV date, due date, CWE-290 (snapshot 06) | 2026-10-17 |
| 2 | The Hacker News: China-Linked Hackers Exploited BeyondTrust Zero-Day | Vendor timeline and quotes, WARP PANDA alias (snapshot 04) | 2026-10-17 |
| 2 | SecurityWeek: Chinese APT Exploited BeyondTrust Vulnerability as Zero-Day | Vendor timeline detail, prior ARMORY CASTLE zero-days (snapshot 05) | 2026-10-17 |
| 1 | BeyondTrust security advisory BT26-05 (referenced, not fetched) | Referenced by the NVD record, KEV entry and CISA; HTTP 403 to automated fetch. No claim depends on it alone | 2026-10-17 |
| 1 | BeyondTrust blog: ARMORY CASTLE and BT26-05 (referenced, not fetched) | Referenced by CISA and Mandiant; HTTP 403 to automated fetch. Not used as a source | 2026-10-17 |