enodia-sentinal/go-agent/internal/detectors/ld_preload.go

57 lines
1.4 KiB
Go

// SPDX-License-Identifier: GPL-3.0-or-later
package detectors
import (
"fmt"
"strings"
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model"
)
var suspiciousPreloadPrefixes = []string{
"/tmp/", "/dev/shm/", "/var/tmp/", "/run/user/", "./",
}
// LDPreload ports the global and per-process Python ld_preload detector.
func LDPreload(state model.State) []model.Alert {
alerts := make([]model.Alert, 0)
if state.LDPreload != "" {
alerts = append(alerts, model.Alert{
SID: 100011,
Severity: "CRITICAL",
Signature: "ld_preload",
Classtype: "rootkit-preload",
Key: "ldp:global",
Detail: fmt.Sprintf("/etc/ld.so.preload is non-empty: [%s]",
strings.ReplaceAll(state.LDPreload, "\n", " ")),
PIDs: []int{},
})
}
for _, process := range state.Processes {
preload := process.Environ["LD_PRELOAD"]
if preload == "" || !hasAnyPrefix(preload, suspiciousPreloadPrefixes) {
continue
}
alerts = append(alerts, model.Alert{
SID: 100011,
Severity: "CRITICAL",
Signature: "ld_preload",
Classtype: "rootkit-preload",
Key: fmt.Sprintf("ldp:%d", process.PID),
Detail: fmt.Sprintf(
"pid=%d comm=%s LD_PRELOAD=[%s]", process.PID, process.Comm, preload),
PIDs: []int{process.PID},
})
}
return alerts
}
func hasAnyPrefix(value string, prefixes []string) bool {
for _, prefix := range prefixes {
if strings.HasPrefix(value, prefix) {
return true
}
}
return false
}