50 lines
1.4 KiB
Go
50 lines
1.4 KiB
Go
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package detectors
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/config"
|
|
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model"
|
|
)
|
|
|
|
// Persistence ports the Python persistence detector (SID 100015).
|
|
// PersistenceFiles is an injectable path-to-mtime view; live filesystem
|
|
// collection remains deferred until the sidecar gains configured slow scans.
|
|
func Persistence(state model.State, cfg config.Config) []model.Alert {
|
|
if state.PersistSince == nil {
|
|
return []model.Alert{}
|
|
}
|
|
alerts := make([]model.Alert, 0)
|
|
paths := make([]string, 0, len(state.PersistenceFiles))
|
|
for path := range state.PersistenceFiles {
|
|
paths = append(paths, path)
|
|
}
|
|
sort.Strings(paths)
|
|
for _, path := range paths {
|
|
mtime := state.PersistenceFiles[path]
|
|
if mtime <= *state.PersistSince || !watchedPath(path, cfg.WatchPersistence) {
|
|
continue
|
|
}
|
|
alerts = append(alerts, model.Alert{
|
|
SID: 100015, Severity: "HIGH", Signature: "persistence",
|
|
Classtype: "persistence", Key: "persist:" + path,
|
|
Detail: fmt.Sprintf("persistence file modified: %s", path),
|
|
PIDs: []int{},
|
|
})
|
|
}
|
|
return alerts
|
|
}
|
|
|
|
func watchedPath(path string, roots []string) bool {
|
|
for _, root := range roots {
|
|
root = strings.TrimRight(root, "/")
|
|
if path == root || (root != "" && strings.HasPrefix(path, root+"/")) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|