9 KiB
Enodia Sentinel Incident Response Runbooks
Practical, conservative response playbooks for the alerts Sentinel raises. Each runbook follows the same arc: confirm → preserve → contain → recover, and prefers reversible, manual steps. Sentinel does not perform automatic containment (see THREAT_MODEL.md); these are operator actions.
A note on trust: if you suspect kernel-level compromise, remember that the tools you run (
ss,ps, evenls) may be lying to you. Cross-check from the dashboard on another machine, and when in doubt, capture evidence and analyze the disk offline.
The First Five Minutes
For any alert, before changing anything:
-
Read the snapshot. Every alert writes
alert-*.log(human) andalert-*.json(machine) under/var/log/enodia-sentinel. Note thesignature,sid, severity, PIDs, executable paths, and remote peers. -
Get host state.
enodia-sentinel status— is the daemon healthy, how many alerts, when was the last. -
Triage known noise.
enodia-sentinel triageseparates likely false positives from findings that need a human. -
Build a dry-run response plan. Find the incident and review the proposed actions:
enodia-sentinel incident list enodia-sentinel respond plan <incident-id> -
Preserve evidence before you touch anything:
tar -C /var/log -czf /tmp/enodia-evidence-$(date +%s).tgz enodia-sentinel
Then pick the runbook below that matches the signature.
Runbook 1 — Reverse shell / suspicious egress
Triggers: reverse_shell (sid 100010), egress (sid 100016).
An interpreter wired to a socket, or an interpreter holding a connection to a public IP — the classic interactive-C2 and beaconing shapes.
Confirm
-
Open the snapshot; identify the PID,
comm, parent process, and remote peer. -
Inspect live (these views may be untrustworthy if root is compromised):
ps -o pid,ppid,user,comm,args -p <pid> ls -l /proc/<pid>/fd # which fds are the socket cat /proc/<pid>/environ | tr '\0' '\n' ss -tnp | grep <pid> # the peer -
Is the peer expected? Compare against
egress_allow_cidrsin config. A package manager or browser to a public IP is normal;bash/python/ncis not.
Contain
- Capture the process before killing it (memory/maps if you have tooling), then:
kill -STOP <pid>to freeze, inspect, and only thenkill -9. - Block the peer if it is hostile:
nft add rule inet filter output ip daddr <peer> drop. - Find persistence the shell may have dropped — run Runbook 2.
Recover
- Rotate any credentials that were reachable from the compromised process.
- Rebuild listener/SUID baselines only after the host is confirmed clean.
False positives: legitimate admin scripts, monitoring agents, or P2P clients.
Add trusted egress destinations to egress_allow_cidrs rather than disabling the
detector.
Runbook 2 — Persistence tampering
Triggers: persistence (sid 100015), fim_modified on a watched persistence
path.
A change to cron, a systemd unit, an SSH authorized_keys, a shell rc file, or
sudo/account config — how an attacker survives a reboot.
Confirm
-
The snapshot names the changed path. Diff it against the FIM baseline and package ownership:
enodia-sentinel fim-check enodia-sentinel fim-check --packages # does a package own & vouch for it? -
For SSH keys: is the added key yours? For systemd/cron: does the unit run a binary in a writable or unusual location?
Contain
- Remove the unauthorized entry (the added key, cron line, or unit). Keep a copy in your evidence bundle first.
systemctl disable --now <unit>for a malicious service; check what it spawned.
Recover
- After removing persistence, hunt for the process it launched (Runbook 1) and any trojaned binaries (Runbook 3).
- Re-anchor the baseline only once clean:
enodia-sentinel fim-update.
False positives: legitimate package upgrades and admin edits. The pacman hook
auto-runs fim-update for normal transactions; an unexplained change outside a
transaction is the suspicious case.
Runbook 3 — Trojaned binary / package tampering
Triggers: fim_modified / fim_pkg_modified on a system binary,
pkgdb_tamper (package DB edited out of band), pkg_signature_mismatch
(on-disk file ≠ signed package), pacman_siglevel_disabled.
Confirm
-
Layer the integrity checks from weakest to strongest trust anchor:
enodia-sentinel fim-check --packages # vs FIM baseline + pacman -Qkk enodia-sentinel pkgdb-check # was the local checksum DB rewritten? enodia-sentinel pkgdb-verify --sample 200 # vs signed cache packages (.MTREE) -
pkg_signature_mismatchis the strongest signal: it bypasses the mutable local DB. Treat a mismatch on a system binary as a trojaned file until proven otherwise.pkgdb_tampersuggests someone tried to hide exactly this.
Contain
- Do not execute the suspect binary. If it is currently running, freeze it (Runbook 1).
- Confirm package-signature policy is intact:
enodia-sentinel posture check(flagspacman_siglevel_disabled).
Recover
-
Identify the owning package and reinstall from a trusted source:
pacman -Qo /path/to/binary pacman -S --overwrite '*' <package> # reinstall the verified file enodia-sentinel fim-check --packages # confirm it now matches -
Then re-anchor:
enodia-sentinel fim-updateand re-runpkgdb-check.
False positives: a mid-upgrade snapshot can momentarily disagree. Re-run after the transaction completes; a persistent mismatch is the real finding.
Runbook 4 — Hidden listener / rootkit
Triggers: rootkit_hidden_process (100022), rootkit_hidden_module (100023),
rootkit_hidden_port (100024), promiscuous_interface (100025), and
new_listener (100013) for an unexplained open port.
These come from cross-view checks: the same question asked two ways, answered differently, because something is hiding.
Confirm
-
Re-run the cross-view sweep and capture it:
enodia-sentinel rootcheck -
new_listener: identify the owning process and whether its binary is package-owned. A hidden port thatrootchecksees butssdoes not is far more serious than a forgotten service. -
A
rootkit_hidden_modulenames a live kernel module absent from/proc/modules— strong evidence of an LKM rootkit.
Contain
- Assume user-space tools are compromised. Pivot to the read-only dashboard from another machine to cross-check, and prefer offline analysis.
- Do not
rmmodblindly — capture the module and system state first.
Recover
- A confirmed kernel rootkit means rebuild from known-good media; you cannot reliably clean a host whose kernel is hooked. Preserve the disk image first.
False positives: PID exit races (Sentinel re-verifies hidden PIDs to reduce these) and a legitimately promiscuous interface (a sniffer/monitoring tool you run). Confirm the owning process before escalating.
Runbook 5 — Sensor tampering
Triggers: fim_modified on a Sentinel-owned path (self-integrity), a stale or
missing heartbeat surfaced by the off-box watchdog, or the dashboard going
unreachable.
Disabling the alarm is step zero of a competent intrusion — so a silent or edited Sentinel is itself an alert.
Confirm
-
From the watchdog host (never the protected host):
enodia-sentinel watchdog --url https://<host>:8787 --token <token> --max-age 120Exit 1 means down, unreachable, or stale.
-
On the host (if you still trust it):
enodia-sentinel statusand check whether Sentinel's own binaries/config/units/hook changed:enodia-sentinel fim-check # SELF_PATHS are always watched
Contain
- If Sentinel's files were edited, treat the host as compromised: an attacker with the privilege to edit the sensor had the privilege to do far more.
- Move to evidence-preservation and offline analysis rather than trusting any further local output.
Recover
- Reinstall Sentinel from a trusted source and re-baseline on a clean host.
- Harden against recurrence:
chattr +ion Sentinel's binaries, config, units, baselines, and the pacman hook; keep the watchdog running off-box.
False positives: a legitimate Sentinel upgrade changes its own files — but that should coincide with a package transaction. An edit outside one is the suspicious case.
After any incident
- Keep the evidence bundle; do not delete snapshots while an investigation is open
(retention is bounded by
max_snapshots/max_snapshot_age_days). - Re-baseline (
baseline,fim-update) only once the host is confirmed clean — baselining a compromised host blesses the compromise. - Re-run
enodia-sentinel posture checkto close the hygiene gaps that enabled the intrusion. - The incident-grouping commands (
incident show/export) on the roadmap will eventually automate the evidence-bundle steps above.