229 lines
11 KiB
Markdown
229 lines
11 KiB
Markdown
# Enodia Sentinel Specification
|
|
|
|
This document defines Enodia Sentinel as an IDS, IPS, and EDR system, not only a
|
|
signature IDS. The current implementation is a local Linux sensor with evidence
|
|
capture, integrity monitoring, anti-rootkit checks, a dashboard, alert delivery,
|
|
and dry-run prevention/response planning. The intended product is a defensive
|
|
control plane for a host or small fleet: detect compromise, prevent or contain
|
|
known-bad behavior through explicit operator workflows, prove what changed,
|
|
preserve useful evidence, guide response, and make sensor tampering visible.
|
|
|
|
## Product Definition
|
|
|
|
Enodia Sentinel is a zero-runtime-dependency Linux host security agent. It runs
|
|
as a local daemon, observes high-signal host behavior, records forensic context
|
|
when something suspicious happens, and exposes the result through local files,
|
|
JSON, a read-only dashboard, push notifications, and command-line tools.
|
|
|
|
The long-term product should combine six functions:
|
|
|
|
| Function | Purpose |
|
|
|---|---|
|
|
| Detection | Find active compromise behavior: reverse shells, fileless execution, new listeners, suspicious egress, persistence edits, and privilege-escalation artifacts. |
|
|
| Prevention | Recommend and, after explicit review, apply containment actions such as stopping malicious processes, blocking C2 peers, disabling persistence, or quarantining files. |
|
|
| Integrity | Prove whether important files, packages, baselines, and Sentinel's own footprint changed. |
|
|
| Evidence | Capture enough context for incident response without forcing the operator to reproduce a live state after the attacker is gone. |
|
|
| Response | Provide safe, explicit operator workflows for triage, containment, and recovery. |
|
|
| Assurance | Make the agent itself measurable: heartbeat, dead-man's switch, tamper-evidence, and future remote attestation. |
|
|
|
|
## Design Principles
|
|
|
|
1. **High-signal first.** Prefer detections that are cheap to observe and costly
|
|
for attackers to avoid, even if that means a smaller rule set.
|
|
2. **Evidence over noise.** Every alert should carry enough context to answer
|
|
"what happened, where, and what should I inspect next?"
|
|
3. **Zero dependency core.** The base daemon must run with the Python standard
|
|
library only. Optional layers such as bcc/eBPF may degrade cleanly.
|
|
4. **One local trust boundary is not enough.** On-box checks are useful but
|
|
root can tamper with them. Important anchors should move to signed package
|
|
metadata, immutable filesystem controls, external watchers, or future
|
|
remote attestation.
|
|
5. **Operator control.** Sentinel should recommend response actions before it
|
|
takes them. Destructive containment must be opt-in and auditable.
|
|
6. **Bash prototype remains the oracle.** The original shell implementation and
|
|
red-team harness preserve behavioral compatibility for core signatures.
|
|
|
|
## Current Scope: Local IDS/IPS/EDR
|
|
|
|
### Poll Detectors
|
|
|
|
The daemon builds one `SystemState` per sweep and runs pure detector functions
|
|
against cached process and socket data:
|
|
|
|
| Detector | Signal |
|
|
|---|---|
|
|
| `reverse_shell` | Interpreter with a network socket on fd 0/1/2. |
|
|
| `ld_preload` | Non-empty `/etc/ld.so.preload` or writable-path `LD_PRELOAD`. |
|
|
| `deleted_exe` | Process executing from a deleted file or `memfd:` image. |
|
|
| `input_snooper` | Non-allowlisted process holding keyboard/input/HID devices open. |
|
|
| `credential_access` | Non-allowlisted process reading credential databases, private keys, browser stores, or secret profiles. |
|
|
| `stealth_network` | Non-allowlisted raw, SCTP, DCCP, packet, MPTCP, TIPC, XDP, or vsock activity. |
|
|
| `memory_obfuscation` | Non-allowlisted executable anonymous/memfd/deleted mappings, RWX memory, or mapped process-hiding libraries. |
|
|
| `new_listener` | Listening socket absent from the startup baseline. |
|
|
| `new_suid` | New SUID/SGID binary, critical in writable locations. |
|
|
| `persistence` | Changes to cron, systemd units, SSH keys, shell rc files, and similar persistence locations. |
|
|
| `egress` | Interpreter with an established connection to a public IP. |
|
|
|
|
### Event Detection
|
|
|
|
Optional bcc eBPF monitors feed event rule engines. The `execve` stream closes
|
|
the polling gap for short-lived commands and supports custom TOML rules without
|
|
code changes. The syscall stream watches short-lived memory and anti-analysis
|
|
behavior: RWX `mprotect`/`mmap`, `memfd_create`, sensitive `ptrace`, seccomp,
|
|
cross-process memory access, and memory locking. Failure is fail-safe: if a
|
|
probe cannot load, polling continues.
|
|
|
|
### Integrity and Tamper-Evidence
|
|
|
|
Sentinel includes several integrity layers:
|
|
|
|
| Layer | Current behavior |
|
|
|---|---|
|
|
| FIM baseline | SHA-256 baseline for critical files and Sentinel's own footprint. |
|
|
| Package verification | Optional `pacman -Qkk` verification for package-owned files. |
|
|
| Package DB anchor | Detects out-of-band edits to `/var/lib/pacman/local`. |
|
|
| Signed-package anchor | Compares on-disk files to `.MTREE` hashes from cached signed packages. |
|
|
| Heartbeat | Writes daemon liveness for local dashboard and external watchdog use. |
|
|
| Rootcheck | Cross-view checks for hidden processes, processes hidden from `ps`, hidden modules, hidden TCP/UDP/raw/special-protocol sockets, promiscuous interfaces, known rootkit modules, raw ICMP/SCTP-style channels, and kernel/module taint. |
|
|
|
|
### Evidence Capture
|
|
|
|
When a fresh alert survives cooldown, Sentinel writes:
|
|
|
|
- A human-readable snapshot.
|
|
- A JSON snapshot suitable for automation and SIEM import.
|
|
- Relevant process tree, sockets, environment hints, file descriptors, and
|
|
response guidance.
|
|
- Event log entries and dashboard-visible status.
|
|
|
|
### Operator Interfaces
|
|
|
|
| Interface | Role |
|
|
|---|---|
|
|
| CLI | Run daemon, one-shot checks, baseline management, FIM checks, package DB checks, rootcheck, posture audit, incident review/export, triage, status/watchdog, and response planning. |
|
|
| Logs | Durable local evidence under `/var/log/enodia-sentinel`. |
|
|
| Dashboard | HTTPS-only read-only web view for status, incidents, timelines, alert browsing, posture findings, event tail, and response-plan previews. |
|
|
| Push | ntfy, Pushover, and generic webhook notifications. |
|
|
| Red-team harness | Safe drills for testing signatures and demos. |
|
|
|
|
CLI-generated response plans are durable artifacts: `respond plan` writes the
|
|
reviewed dry-run plan under `response-plans/` and appends a JSONL
|
|
`response-audit.log` record. Dashboard/API previews remain read-only and do not
|
|
create artifacts.
|
|
|
|
Current IPS scope is explicit prevention workflow, not transparent inline
|
|
enforcement. Sentinel can recommend evidence preservation, process
|
|
freeze/termination, outbound IP blocks, systemd unit disablement, suspicious-file
|
|
quarantine, package-owner lookup, and follow-up verification. It does not
|
|
execute those commands until a future audited `--apply` workflow is designed,
|
|
tested, and documented.
|
|
|
|
## Target Scope: Host Security Platform
|
|
|
|
The next product shape should make Enodia useful before, during, and after an
|
|
incident.
|
|
|
|
### Prevent
|
|
|
|
- Configuration posture checks for risky SSH, sudo, systemd, cron, kernel,
|
|
package manager, firewall, and service settings.
|
|
- Baseline drift reports for newly exposed services, new SUID files, new
|
|
autostarts, new users/groups, and sensitive permission changes.
|
|
- A policy mode that can fail CI or package build checks for unsafe host images.
|
|
|
|
### Detect
|
|
|
|
- More event sources: `tcp_connect`, `bind`, `accept`, file-write events for
|
|
persistence paths, module loading, privilege transitions, and LSM hooks.
|
|
- Correlation across signals: "web service spawned shell" + "new listener" +
|
|
"persistence write" should become one incident, not three unrelated alerts.
|
|
- Optional YARA-style and Sigma-like local rules if they can stay dependency
|
|
light and operator-readable.
|
|
|
|
### Investigate
|
|
|
|
- Incident timeline files derived from event log, snapshots, FIM diffs,
|
|
package transactions, process lineage, and network observations.
|
|
- Stable incident IDs that group related alerts over time.
|
|
- `enodia-sentinel incident show <id>` and `incident export <id>` workflows.
|
|
|
|
### Respond
|
|
|
|
- Safe containment actions behind explicit flags:
|
|
stop a process, disable a systemd unit, remove a persistence entry, block an
|
|
IP with nftables, quarantine a file, or freeze evidence.
|
|
- Dry-run by default, with JSON plans that can be reviewed before execution.
|
|
- Response playbooks that are code-reviewed data files, not shell snippets
|
|
pasted into documentation.
|
|
|
|
### Recover
|
|
|
|
- Package restore guidance: identify owning package, verify cache signature,
|
|
reinstall package, and re-run integrity checks.
|
|
- Baseline reconciliation workflow after confirmed legitimate changes.
|
|
- Post-incident report generation from captured evidence.
|
|
|
|
### Assure
|
|
|
|
- External anchor storage for baselines and package DB fingerprints.
|
|
- Signed snapshots or hash-chained event logs.
|
|
- Remote watchdog improvements and eventually fleet controller support.
|
|
- Optional TPM/IMA integration for machines that can support measured boot.
|
|
|
|
## Data Model
|
|
|
|
The current `Alert` object is the public detection unit:
|
|
|
|
| Field | Meaning |
|
|
|---|---|
|
|
| `sid` | Stable signature ID for tuning, documentation, and downstream rules. |
|
|
| `severity` | `MEDIUM`, `HIGH`, or `CRITICAL`. |
|
|
| `signature` | Stable machine-readable detection name. |
|
|
| `classtype` | Snort/Suricata-style category. |
|
|
| `key` | Cooldown and deduplication identity. |
|
|
| `detail` | Human-readable explanation. |
|
|
| `pids` | Process IDs for snapshot deep dives. |
|
|
|
|
Incident grouping adds an `incident_id` at the snapshot-report level (not inside
|
|
each `Alert`), so it groups one or more alerts without changing the alert JSON
|
|
schema. Grouping is process-lineage first, with a time-window fallback for
|
|
PID-less alerts; see the [command reference](COMMAND_REFERENCE.md) and
|
|
[roadmap](ROADMAP.md).
|
|
|
|
## Configuration Model
|
|
|
|
Configuration is a TOML file loaded at startup. Unknown keys are ignored so
|
|
newer config templates remain tolerable on older agents, but documentation
|
|
should clearly mark version-specific fields. Existing defaults should prefer
|
|
detection correctness over suppression. Convenience suppression knobs should
|
|
remain explicit and reviewable.
|
|
|
|
## Security Model
|
|
|
|
Sentinel runs as root because it must inspect root-owned files, process state,
|
|
file descriptors, and sockets. The systemd unit should continue to keep the
|
|
root process narrow: read-mostly, constrained writable paths, no new privileges,
|
|
restricted namespaces, and only the capabilities needed for the enabled layers.
|
|
|
|
Local root can eventually defeat any purely local sensor. Sentinel's answer is
|
|
layering: signed package metadata, immutable files, off-box watchdogs, external
|
|
anchors, and future kernel/attestation features.
|
|
|
|
## Non-Goals
|
|
|
|
- Replacing a full enterprise SIEM.
|
|
- Silent self-hiding or rootkit-like persistence.
|
|
- Automatic destructive remediation without explicit operator approval.
|
|
- Shipping a broad dependency tree in the default agent.
|
|
- Claiming complete protection against a custom kernel implant.
|
|
|
|
## Acceptance Criteria For New Platform Features
|
|
|
|
A feature is ready when it has:
|
|
|
|
- A stable `sid`/signature or documented command contract.
|
|
- Unit tests for pure logic and a safe integration path where practical.
|
|
- JSON output or a durable artifact suitable for automation.
|
|
- Configuration documented in the sample TOML and README or relevant docs.
|
|
- Failure behavior that does not take down the daemon.
|
|
- Clear operator guidance for false positives, limitations, and response.
|