Answers two hard questions: "what guards the hashes FIM trusts?" and "how do we make the sensor itself hard to silently disable?" — within the honest limit that a root attacker who shares your privileges can't be fully stopped on-box, only made loud. - pkgdb.py: guards the package DB that `pacman -Qkk` trusts. Anchors a fingerprint of /var/lib/pacman/local (refreshed ONLY by the pacman hook) and cross-checks pacman.log; a DB change with no logged transaction is flagged pkgdb_tamper (CRITICAL, sid 100021) — catches an attacker rewriting a stored checksum to mask a modified binary. Verified end-to-end against a simulated hash-overwrite. - selfprotect.py: Sentinel's own binaries/config/units/hook are always in the FIM watch set (self-integrity); a heartbeat is written each loop; an external `watchdog` command polls a remote dashboard and pushes if the sensor goes silent or unreachable — silence becomes the alarm. - daemon: heartbeat + slow-cadence pkgdb check; DB anchor re-anchored in build_fim_baseline so the pacman hook refreshes it after each transaction - web: /api/status now reports heartbeat_age/stale; dashboard shows it - cli: pkgdb-check, watchdog (--url/--token/--max-age, bypasses min-severity) - config: pkgdb_verify/_interval, heartbeat_max_age - README: threat model (trust-anchor problem) + hardening layers (immutability, signed-package + external anchor); reframes "anti-rootkit" as tamper-evidence - tests: +8 (DB fingerprint, anchor/transaction logic, pacman.log parse, heartbeat + watchdog verdicts). 80/80 pass Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
34 lines
1.1 KiB
TOML
34 lines
1.1 KiB
TOML
[build-system]
|
|
requires = ["setuptools>=61"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "enodia-sentinel"
|
|
version = "0.6.0"
|
|
description = "Host intrusion-detection daemon — signature-based detection of reverse shells, LD_PRELOAD rootkits, fileless malware, and persistence tampering"
|
|
readme = "README.md"
|
|
requires-python = ">=3.11"
|
|
license = { text = "GPL-3.0-or-later" }
|
|
authors = [{ name = "Enodia" }]
|
|
keywords = ["security", "ids", "hids", "detection", "linux", "forensics"]
|
|
classifiers = [
|
|
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
"Operating System :: POSIX :: Linux",
|
|
"Programming Language :: Python :: 3",
|
|
"Topic :: Security",
|
|
]
|
|
# Zero runtime dependencies — stdlib only, by design (a system security
|
|
# daemon should not pull in a dependency tree it has to trust and update).
|
|
dependencies = []
|
|
|
|
[project.scripts]
|
|
enodia-sentinel = "enodia_sentinel.cli:main"
|
|
|
|
[project.optional-dependencies]
|
|
dev = ["pytest"]
|
|
|
|
[tool.setuptools.packages.find]
|
|
include = ["enodia_sentinel*"]
|
|
|
|
[tool.setuptools.package-data]
|
|
enodia_sentinel = ["static/*.html"]
|