Cybersecurity-Projects/PROJECTS/beginner/systemd-persistence-scanner/internal/scanner/patterns.go

149 lines
3.7 KiB
Go

/*
©AngelaMos | 2026
patterns.go
Compiled regular expressions for detecting suspicious persistence content
Centralizes all pattern matching used across scanner modules so each
scanner does not duplicate regex compilation. Patterns cover network
tool invocations, encoding/obfuscation, reverse shell signatures,
temporary directory references, and alias hijacking.
*/
package scanner
import (
"regexp"
"github.com/CarterPerez-dev/sentinel/pkg/types"
)
var NetworkToolPattern = regexp.MustCompile(
`\b(curl|wget|nc|ncat|nmap|socat)\b`,
)
var DownloadExecPattern = regexp.MustCompile(
`(curl|wget)\s+.*\|\s*(bash|sh|zsh|dash)` +
`|` +
`(curl|wget)\s+.*-o\s+/tmp/`,
)
var EncodingPattern = regexp.MustCompile(
`\b(base64\s+-d|base64\s+--decode|xxd\s+-r|openssl\s+enc)\b` +
`|` +
`\becho\s+[A-Za-z0-9+/=]{20,}\s*\|`,
)
var ReverseShellPattern = regexp.MustCompile(
`/dev/tcp/` +
`|` +
`\bmkfifo\b.*\bnc\b` +
`|` +
`\bsocat\b.*\bexec\b` +
`|` +
`python[23]?\s+-c\s+.*socket` +
`|` +
`perl\s+-e\s+.*socket` +
`|` +
`ruby\s+-rsocket`,
)
var TempDirPattern = regexp.MustCompile(
`(/tmp/|/dev/shm/|/var/tmp/)`,
)
var ScriptLangPattern = regexp.MustCompile(
`\b(python[23]?|perl|ruby)\s+-[ce]\b`,
)
var AliasHijackPattern = regexp.MustCompile(
`alias\s+(sudo|su|ssh|ls|cat|id|whoami|passwd)\s*=`,
)
var LDPreloadPattern = regexp.MustCompile(
`\b(LD_PRELOAD|LD_LIBRARY_PATH)\s*=`,
)
var PathManipPattern = regexp.MustCompile(
`\bPATH\s*=\s*["']?(/tmp|/dev/shm|/var/tmp)`,
)
var NohupPattern = regexp.MustCompile(
`\bnohup\b.*&` +
`|` +
`&\s*disown`,
)
var EvalExecPattern = regexp.MustCompile(
`\b(eval|exec)\s+["']?\$\(.*(curl|wget|nc|base64)`,
)
var SuidPattern = regexp.MustCompile(
`chmod\s+[ugo]*\+s\b` +
`|` +
`chmod\s+[247][0-7]{3}\b`,
)
var AccountCreatePattern = regexp.MustCompile(
`\b(useradd|adduser|usermod)\b`,
)
var ImmutablePattern = regexp.MustCompile(
`\bchattr\s+[+-]i\b`,
)
var PersistenceInstallPattern = regexp.MustCompile(
`\bsystemctl\s+(enable|daemon-reload)\b` +
`|` +
`\bcrontab\s+-[le]\b`,
)
var EncryptedC2Pattern = regexp.MustCompile(
`\bopenssl\s+s_client\b`,
)
type PatternMatch struct {
Pattern *regexp.Regexp
Severity types.Severity
Label string
}
var SuspiciousPatterns = []PatternMatch{
{ReverseShellPattern, types.SeverityCritical, "reverse shell pattern"},
{DownloadExecPattern, types.SeverityHigh, "download-and-execute chain"},
{EncodingPattern, types.SeverityHigh, "encoded/obfuscated payload"},
{NetworkToolPattern, types.SeverityMedium, "network tool invocation"},
{ScriptLangPattern, types.SeverityMedium, "inline script execution"},
{TempDirPattern, types.SeverityMedium, "temporary directory reference"},
{AliasHijackPattern, types.SeverityHigh, "alias hijacking"},
{LDPreloadPattern, types.SeverityCritical, "LD_PRELOAD manipulation"},
{PathManipPattern, types.SeverityHigh, "PATH manipulation to temp dir"},
{NohupPattern, types.SeverityMedium, "background process launch"},
{EvalExecPattern, types.SeverityHigh, "dynamic eval/exec"},
{SuidPattern, types.SeverityCritical, "SUID bit manipulation"},
{AccountCreatePattern, types.SeverityHigh, "account creation/modification"},
{ImmutablePattern, types.SeverityHigh, "file attribute manipulation"},
{
PersistenceInstallPattern,
types.SeverityMedium,
"persistence self-installation",
},
{EncryptedC2Pattern, types.SeverityHigh, "encrypted C2 channel"},
}
func MatchLine(
line string,
) (matched bool, sev types.Severity, label string) {
best := types.SeverityInfo
for _, p := range SuspiciousPatterns {
if p.Pattern.MatchString(line) {
if !matched || p.Severity > best {
best = p.Severity
label = p.Label
}
matched = true
}
}
return matched, best, label
}