41 lines
1.4 KiB
Go
41 lines
1.4 KiB
Go
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package detectors
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/config"
|
|
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model"
|
|
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/netutil"
|
|
)
|
|
|
|
// Egress ports interpreter-to-public-IP detection (SID 100016).
|
|
func Egress(state model.State, cfg config.Config) []model.Alert {
|
|
alerts := make([]model.Alert, 0)
|
|
for _, socket := range state.Sockets {
|
|
// Only established interpreter-owned sockets qualify. Listeners and
|
|
// connection setup states are handled by other detector families.
|
|
if socket.State != "ESTAB" || !cfg.Interpreters[socket.Comm] {
|
|
continue
|
|
}
|
|
host, port := netutil.SplitHostPort(socket.Peer)
|
|
// Private/special addresses and explicit trusted CIDRs are intentionally
|
|
// silent so routine local services and operator infrastructure stay quiet.
|
|
if !netutil.IsPublicIP(host) || netutil.IPInCIDRs(host, cfg.EgressAllowCIDRs) {
|
|
continue
|
|
}
|
|
alerts = append(alerts, model.Alert{
|
|
SID: 100016,
|
|
Severity: "HIGH",
|
|
Signature: "egress",
|
|
Classtype: "c2-exfil",
|
|
Key: fmt.Sprintf("egr:%s:%s", optionalPythonInt(socket.PID), host),
|
|
Detail: fmt.Sprintf(
|
|
"pid=%s comm=%s -> %s:%s (interpreter to public IP)",
|
|
optionalPythonInt(socket.PID), socket.Comm, host, port),
|
|
PIDs: alertPIDs(socket.PID),
|
|
})
|
|
}
|
|
return alerts
|
|
}
|