53. Under Attack: endpoint telemetry chains and automatic isolation
This guide describes Lawliet 1.5.15.s (the current release). Screens, commands and procedures may change in later versions; the usage guide is updated with each release. Check the version your server runs under Settings > Platform or with ./lawliet version, and see the Releases page for what changed.
From 1.5.15.s the agents send endpoint telemetry: which processes start and from which parent, with their command lines, which connections they open and which files they write. Under Attack reads that telemetry for four attack patterns that are almost never innocent, called chains. A chain is never one log line: it is two or more steps of one attack on one host, linked process by process.
What a chain does:
- it counts as one trigger signal for suggestions and automatic starts (chapter 50);
- it may isolate the host it ran on - only when a second, different source agrees, and only where isolation is switched on (always inside an active Under Attack, off by default outside);
- when an activation starts, the telemetry around each alert and chain on the hosts in scope is copied into the incident record, and the war room shows each affected host's chain as a story and its process tree.
Permissions:
| Task | Permission | Four-eyes |
|---|---|---|
| See chains, the affected hosts in the war room and the chain-isolation settings | View Under Attack | - |
| See command lines, process trees and the copied telemetry | View Under Attack and Search logs | - |
| Switch chain isolation ON, or let it reach more hosts | Prepare Under Attack plans and Execute containment | yes - critical action "Approve an Under Attack plan" |
| Narrow chain isolation or switch it off | Prepare Under Attack plans | no - the safe direction is never held |
| Mark a chain a false positive | Prepare Under Attack plans | yes - same critical action |
| Release an isolation made outside an activation | Execute containment | yes - critical action "Run a containment action" |
53.1 The four chains#
| Chain | What has to be seen on one host | ATT&CK |
|---|---|---|
| Office document ran a script that downloaded and executed a payload | In order: an Office application (Word, Excel, PowerPoint, Outlook, LibreOffice...) starts a script host or a LOLBin (PowerShell, cmd, mshta, rundll32, certutil, sh, curl...), its nearest Office ancestor at most three generations up; that subtree connects out within 2 minutes; within 5 minutes of the connection a process of the subtree runs a file the subtree wrote, loads it, or runs from a user-writable folder. | T1566.001, T1204.002, T1059, T1105 |
| LSASS memory dumped (credential theft) | In order: rundll32 comsvcs MiniDump, then a file written by that process within 2 minutes; or a dump tool (procdump, rdrleakdiag, sqldumper, createdump) naming lsass, then its .dmp within 2 minutes - only when the tool runs from a user-writable folder or below a remote-execution or script host (WMI, WinRM, PsExec, mshta, wscript) or Office. An administrator's support dump from a tools folder is not a chain, nor is a command line that merely names a Mimikatz module. | T1003.001 |
| Mass file encryption pattern (ransomware) | One process renames 25 or more files to the same NEW appended extension within two minutes across at least two folders (rotation suffixes such as .1 or -20261018 are not new extensions); or overwrites (not creates) 100 or more existing files in five or more folders within two minutes while running from a user-writable folder, or while a process of its own tree deletes ALL shadow copies or disables recovery. Installers, updaters, sync clients, git, package managers, log rotation and backup tools are not counted. | T1486 |
| Reverse shell | A process started with the reverse-shell idiom of its own class - an interactive shell whose streams are a /dev/tcp socket (bash -i >& /dev/tcp/...), nc -e /bin/sh or ncat --sh-exec, socat exec:sh, a Python socket with a pty or dup2, PowerShell TCPClient + GetStream + iex - and, within 15 seconds, an outbound connection by it, its child or its netcat parent to an address that is not the host itself. | T1059.004, T1059.001 |
What the profile collects matters: the light telemetry profile sends no file writes, so the mass-encryption and LSASS chains cannot be seen there. Tested look-alikes that are not chains: a port check such as bash -c '</dev/tcp/db/5432', start-stop-daemon --exec, a grep or findstr for a Mimikatz module name, logrotate with dateext or numbered rotation, a backup job after pruning the oldest shadow copy, an administrator's procdump from a tools folder, git and package installs. Slow chains. The same ordered sequence spread over longer windows - a sleep before the download (connection within 30 minutes), a payload run later or by a scheduled task (the file the script wrote runs within an hour, by any process), a reverse shell connecting within 10 minutes, encryption throttled (50 renames to one new extension within 30 minutes) - is a slow chain: it counts as a signal at a lower weight (25 instead of 40) and isolates a host only inside an activation. Encryption split across worker processes is aggregated on their launcher.
Known gaps, by design (high confidence first): a dump tool run by pid or renamed, VBA that downloads and runs without a script host, a macro launched through WMI, in-place encryption from Program Files without recovery removal, a reverse shell from a script file, and anything slower than the slow windows. Sigma rules on the same telemetry still alert on several of these.
A chain on many hosts is still one signal (one behaviour), like one decoy kind. A Sigma rule that fired on the same events as a chain is the same observation, not corroboration.
53.2 Two observers before any isolation#
The agent on a host is one observer. A compromised host can lie about itself, so the host's own agent alone never isolates it - in every mode. A second source has to report the same attack within 30 minutes of the chain. It must be:
- independent and authenticated: another host's agent (its own shipped events), a decoy on another host or a server canary, another host's chain or DLP report. A log line nobody signed - syslog, an HTTP shipper, the host forwarding its own logs, another agent relaying this host's logs - never counts, nor does anything the host's own agent reported;
- in agreement, compared on exact structured fields, never on text:
| Second source | Agrees when |
|---|---|
| A detection on another host's agent | Its events involve the chain's remote endpoint, exactly, AND it is the same kind of activity: a technique of the chain's families, or command and control / exfiltration (T1071, T1095, T1105, T1571, T1573, T1090, T1041, T1048, T1567). Or: this host's exact address in a HIGH or CRITICAL detection of exactly one of the chain's techniques (a sub-technique of the family is not enough). A detection that merely names the host does not agree. |
| A decoy on another host, or a server canary | It was touched from this host's address, or from the chain's remote endpoint. |
| Another host's chain | It connected to the same remote endpoint, or to this host. |
| Another host's DLP report (when DLP counts, chapter 50) | Its destination is the chain's remote endpoint, exactly. |
An endpoint ties two observations only when it is nobody's shared infrastructure: never a private address (forward proxies, internal DNS, gateways), never an address listed as shared infrastructure (53.5), and normally not an address five or more hosts' telemetry connected to in the hour around the chain (a NAT, a CDN, an unlisted proxy). Hosts that are themselves under suspicion (a chain or a detection of their own) are not counted for that, so an outbreak beaconing to one C2 does not make it "shared"; and on such a busy address that you did not list, high or critical command-and-control or exfiltration detections from two different agents still agree. Lawliet ships no vendor proxy ranges: behind a cloud web proxy (Zscaler, Netskope or similar), list its egress ranges and your NAT addresses as shared infrastructure before switching chain isolation on. A host's address ties nothing when another host reports the same one (NAT, a stale record). The second source must be of real weight (medium severity or above).
Outside an activation, one other agent is not enough: a single agent can be the attacker's own (a fabricated decoy trip "from" the victim). It takes a decoy observed by Lawliet itself (a server canary) or two other agents that cannot be the same one. Inside an activation one agreeing observer is enough.
If nobody agrees within 30 minutes, the chain is recorded as not corroborated and isolates nothing; it still counts as a signal, and a later sighting of the same chain opens the decision again.
53.3 When a chain isolates its host#
- During an active Under Attack, for every host in the plan's scope: always on - except that an AUTOMATIC activation no person has confirmed yet honours the hold of 53.5 below (the same storm that latched the hold may have started it): no fresh budget until a person confirms it. The isolation is the activation's own isolate step: it goes through the never-touch lists, the blast-radius cap (every chain kind counts against it, mass encryption included) and is written to the activation's ledger with its exact undo, like every other change (51.5).
- Outside an activation: only where an administrator switched chain isolation on (53.5) for that chain and that host. The same never-touch lists apply; a tier-0 host is not isolated automatically, nor is a domain controller - recognised from the AD collection (chapter 14), not from what the host says: a host that only claims to be a DC where no AD collection can check it waits for a person. The blast-radius numbers of the Under Attack settings (51.8) apply to every isolation outside activations together and the cap latches: once reached, no host is isolated automatically on a chain - however long the attack or the authorised pentest goes on - until a second administrator releases it (53.5); a critical review item and a notification say so. Only high-confidence chains isolate outside an activation. The command is the same isolation the defence console sends. It reads isolating until the host confirms it (then isolated, or failed); its exact inverse is kept with the chain. A host released from the defence console reads released.
- Never while the automatic kill switch is engaged (50.5) or its setting cannot be read, and never in the sandbox (sandbox hosts get nothing).
Every decision - isolated, refused and why, waiting for a second observer - is shown with the chain and written to the audit log.
Residual risks#
- Outside an activation, two agents an attacker controls can together agree on the chain of a host that has its own chain (a chain cannot be planted on a host the attacker does not control, and the observers must be two different agents).
- An agent reports its own address. A compromised agent reporting a victim's address makes it ambiguous, so the victim loses address-based agreement: that fails safe (less isolation).
53.4 The war room: affected hosts#
The war room (51.5) and the record of an ended activation have a section Affected hosts: story and process tree. One entry per host in scope with a chain or copied telemetry:
- The chain, step by step - the story: the Office application, the script it started, the connection, the file written, what ran. Each step with its time and command line.
- What was done - isolated through the activation (with its ledger change), or why not: only one observer, isolation not on for this host, refused by a guard (with the guard's reason). The second observer that agreed is named.
- Process tree - the processes around the chain, nested by parent, with each one's connections and file writes; the chain's own processes are highlighted.
- Incident record - how many telemetry windows and events were copied when the activation started.
Command lines and the tree are log data: without Search logs the section says what happened but not the detail.
What is copied into the incident record#
When an activation starts, for every host in its scope Lawliet takes each alert and chain of the 24 hours before, adds 15 minutes either side, merges windows that overlap, and copies the telemetry of those windows into the activation's record (at most 25 windows of 1,000 events each, newest first; a window cut at its cap is marked). The log store keeps telemetry 14 days by default; the copy stays as long as the activation is kept. A drill copies nothing.
53.5 Settings: automatic isolation outside an activation#
Under attack > Automatic isolation on telemetry chains. Off by default.
Procedure: switch chain isolation on#
- Tick the chains that may isolate a host.
- Either tick Every host, or list the host groups (one per line). Only the members the groups list when this is approved are covered: a host added to a group later, or another group renamed to the same name, is not covered until a new approval. A group that does not exist is refused. List shared infrastructure that must never tie two observations together: your cloud web proxy's egress ranges (from the vendor's published list), NAT addresses, proxies, DNS servers and gateways.
- Save (switching on needs a second signature). The request waits for a second administrator with the "Approve an Under Attack plan" critical action. Saving needs Execute containment too: enabling it is the authorisation for isolations that nobody signs later.
Procedure: narrow or switch it off#
Untick chains or remove groups and Save. One signature: the safe direction is never held.
Procedure: release the held blast-radius cap#
When the cap was reached, the panel says Held. Check whether an authorised test or a real attack is under way (start an Under Attack plan for a real one), then Release the hold (needs a second signature) - critical action "Approve an Under Attack plan". The release grants a fresh budget of the cap from now; the chains the hold refused are decided again, each still needing its observers and passing every guard. API: POST /api/v1/under-attack/chain-isolation/release-cap.
Procedure: release an isolation made outside an activation#
POST /api/v1/under-attack/chains/{id}/revert sends the exact inverse kept with the chain (the release of the isolation); it needs Execute containment and a second signature. An isolation made by an activation is rolled back from the activation's ledger instead (51.5, 51.6).
Procedure: mark a chain a false positive#
POST /api/v1/under-attack/chains/{id}/false-positive with a reason, for example a red-team exercise. The chain stops counting as a signal and can no longer isolate. Not offered for a chain that isolated its host: release the isolation first. Needs a second signature.
The list of recent chains and their decisions: GET /api/v1/under-attack/chains.
53.6 In the sandbox#
The sandbox has an activation started by a chain: Endpoint chain response (demo). A finance desk opened a macro document; Word started PowerShell, which downloaded a loader and ran it; two minutes later the same desk opened the decoy share on the file server. The chain plus the decoy started the plan automatically and the desk was isolated through the ledger. On a Linux application host a reverse shell was seen too, but only by that host's own agent: it is on the record as only one observer and isolated nothing.



