feat(go): add Phase 1 parity sidecar
This commit is contained in:
parent
65f5be6420
commit
f02509aab5
22 changed files with 947 additions and 6 deletions
51
go-agent/internal/detectors/deleted_exe.go
Normal file
51
go-agent/internal/detectors/deleted_exe.go
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// Package detectors contains pure Go ports of Sentinel's poll detectors.
|
||||
package detectors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model"
|
||||
)
|
||||
|
||||
var suspiciousDeletedPrefixes = []string{"/tmp/", "/dev/shm/", "/var/tmp/", "/run/"}
|
||||
|
||||
// DeletedExe ports enodia_sentinel.detectors.deleted_exe exactly: memfd-backed
|
||||
// executables always alert, while deleted executables alert only from writable
|
||||
// or runtime paths.
|
||||
func DeletedExe(state model.State) []model.Alert {
|
||||
alerts := make([]model.Alert, 0)
|
||||
for _, process := range state.Processes {
|
||||
if !isFileless(process.Exe) {
|
||||
continue
|
||||
}
|
||||
alerts = append(alerts, model.Alert{
|
||||
SID: 100012,
|
||||
Severity: "CRITICAL",
|
||||
Signature: "deleted_exe",
|
||||
Classtype: "fileless-execution",
|
||||
Key: fmt.Sprintf("del:%d", process.PID),
|
||||
Detail: fmt.Sprintf(
|
||||
"pid=%d comm=%s exe=[%s]", process.PID, process.Comm, process.Exe),
|
||||
PIDs: []int{process.PID},
|
||||
})
|
||||
}
|
||||
return alerts
|
||||
}
|
||||
|
||||
func isFileless(exe string) bool {
|
||||
if strings.Contains(exe, "memfd:") {
|
||||
return true
|
||||
}
|
||||
if !strings.Contains(exe, "(deleted)") {
|
||||
return false
|
||||
}
|
||||
for _, prefix := range suspiciousDeletedPrefixes {
|
||||
if strings.HasPrefix(exe, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
28
go-agent/internal/detectors/deleted_exe_test.go
Normal file
28
go-agent/internal/detectors/deleted_exe_test.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package detectors
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model"
|
||||
)
|
||||
|
||||
func TestDeletedExeMatchesPythonCases(t *testing.T) {
|
||||
state := model.State{Processes: []model.Process{
|
||||
{PID: 300, Comm: "tmp", Exe: "/tmp/x (deleted)"},
|
||||
{PID: 301, Comm: "memfd", Exe: "/memfd:foo (deleted)"},
|
||||
{PID: 302, Comm: "upgrade", Exe: "/usr/bin/x (deleted)"},
|
||||
{PID: 303, Comm: "normal", Exe: "/usr/bin/x"},
|
||||
}}
|
||||
alerts := DeletedExe(state)
|
||||
if len(alerts) != 2 {
|
||||
t.Fatalf("expected two alerts, got %#v", alerts)
|
||||
}
|
||||
if alerts[0].SID != 100012 || alerts[0].Signature != "deleted_exe" || alerts[0].PIDs[0] != 300 {
|
||||
t.Fatalf("unexpected alert: %#v", alerts[0])
|
||||
}
|
||||
if alerts[1].Key != "del:301" {
|
||||
t.Fatalf("unexpected memfd alert: %#v", alerts[1])
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue