71 lines
2.5 KiB
Python
71 lines
2.5 KiB
Python
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
"""Tests for event-driven syscall rules; pure, no BPF needed."""
|
|
import unittest
|
|
|
|
from enodia_sentinel.alert import Severity
|
|
from enodia_sentinel.events.syscall_event import SyscallEvent
|
|
from enodia_sentinel.events.syscall_rules import SyscallRuleEngine
|
|
|
|
|
|
def ev(syscall, arg0=0, arg1=0, arg2=0, arg3=0, text="", pid=10):
|
|
return SyscallEvent(
|
|
pid=pid, ppid=1, uid=1000, comm="hoxha", syscall=syscall,
|
|
arg0=arg0, arg1=arg1, arg2=arg2, arg3=arg3, text=text,
|
|
)
|
|
|
|
|
|
class TestSyscallEvent(unittest.TestCase):
|
|
def test_json_shape(self):
|
|
d = ev("memfd_create", arg0=1, text="stage").to_dict()
|
|
self.assertEqual(d["syscall"], "memfd_create")
|
|
self.assertEqual(d["args"][0], 1)
|
|
self.assertEqual(d["text"], "stage")
|
|
|
|
|
|
class TestDefaultSyscallRules(unittest.TestCase):
|
|
def setUp(self):
|
|
self.engine = SyscallRuleEngine()
|
|
|
|
def sids(self, event):
|
|
return {a.sid for a in self.engine.match(event)}
|
|
|
|
def alert(self, event):
|
|
return next(iter(self.engine.match(event)))
|
|
|
|
def test_mprotect_rwx_alerts(self):
|
|
self.assertIn(100060, self.sids(ev("mprotect", arg2=0x6)))
|
|
|
|
def test_mprotect_read_exec_ignored(self):
|
|
self.assertNotIn(100060, self.sids(ev("mprotect", arg2=0x5)))
|
|
|
|
def test_mmap_rwx_alerts(self):
|
|
self.assertIn(100061, self.sids(ev("mmap", arg2=0x7)))
|
|
|
|
def test_memfd_create_alerts(self):
|
|
alert = self.alert(ev("memfd_create", text="payload"))
|
|
self.assertEqual(alert.sid, 100062)
|
|
self.assertEqual(alert.severity, Severity.MEDIUM)
|
|
self.assertIn("payload", alert.detail)
|
|
|
|
def test_ptrace_sensitive_requests_alert(self):
|
|
self.assertIn(100063, self.sids(ev("ptrace", arg0=16)))
|
|
self.assertIn(100063, self.sids(ev("ptrace", arg0=0x4206)))
|
|
|
|
def test_ptrace_other_request_ignored(self):
|
|
self.assertNotIn(100063, self.sids(ev("ptrace", arg0=3)))
|
|
|
|
def test_seccomp_alerts_from_prctl_or_syscall(self):
|
|
self.assertIn(100064, self.sids(ev("prctl", arg0=22)))
|
|
self.assertIn(100064, self.sids(ev("seccomp")))
|
|
|
|
def test_process_vm_alerts(self):
|
|
self.assertIn(100065, self.sids(ev("process_vm_readv", arg0=4242)))
|
|
self.assertIn(100065, self.sids(ev("process_vm_writev", arg0=4242)))
|
|
|
|
def test_mlock_alerts(self):
|
|
self.assertIn(100066, self.sids(ev("mlock")))
|
|
self.assertIn(100066, self.sids(ev("mlockall")))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|