// 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 }