| package bundle |
|
|
| import "strings" |
|
|
| |
| |
| |
| |
| |
| type ScriptOtherAnalyzer struct{} |
|
|
| func (ScriptOtherAnalyzer) Name() string { return "script-other" } |
|
|
| func (ScriptOtherAnalyzer) Handles(kind FileKind) bool { return kind == KindScriptOther } |
|
|
| |
| |
| |
| var scriptOtherIndicatorFamilies = map[string][]string{ |
| "node": {"child_process", "require('child_process')", "exec(", "execsync(", "spawn(", "https.request", "http.request", "net.connect"}, |
| "ruby": {"net::http", "open-uri", "open(\"|", "system(", "`", "%x{", "exec(", "io.popen"}, |
| "powershell": {"invoke-webrequest", "invoke-restmethod", "iwr ", "irm ", "start-process", "downloadstring", "system.net.webclient", "invoke-expression", "iex "}, |
| "batch": {"powershell", "bitsadmin", "certutil -urlcache", "start /b", "reg add"}, |
| "lua": {"os.execute", "io.popen", "socket.http", "require(\"socket"}, |
| "perl": {"lwp::useragent", "system(", "exec(", "`", "io::socket", "use net::"}, |
| "make": {"curl ", "wget ", "$(shell", "&& sh", "| sh", "| bash"}, |
| "docker": {"run curl", "run wget", "run pip", "run npm", "add http", "&& sh", "| sh"}, |
| } |
|
|
| func (ScriptOtherAnalyzer) Analyze(f *File, b *Bundle) ([]Finding, error) { |
| if f == nil { |
| return nil, nil |
| } |
| text := string(f.Sniff) |
| out := sharedIndicatorScan(text, f.RelPath, "script-other") |
|
|
| |
| |
| |
| lang := strings.ToLower(f.ScriptLang) |
| fam := scriptOtherIndicatorFamilies[lang] |
| if len(fam) > 0 { |
| lines := strings.Split(text, "\n") |
| lower := make([]string, len(lines)) |
| for i, l := range lines { |
| lower[i] = strings.ToLower(l) |
| } |
| for i := range lower { |
| window := lower[i] |
| if i+1 < len(lower) { |
| window += "\n" + lower[i+1] |
| } |
| if i+2 < len(lower) { |
| window += "\n" + lower[i+2] |
| } |
| hasPrimitive := matchedAny(window, fam) |
| hasSource := matchedAny(window, envSourceTerms) |
| if hasPrimitive && hasSource { |
| out = append(out, Finding{ |
| Analyzer: "script-other", |
| File: f.RelPath, |
| Signal: "exfil-env-to-network", |
| Severity: SevHigh, |
| Detail: lang + " runtime exec/network primitive co-occurs with env/credential read", |
| Line: i + 1, |
| Corroborated: true, |
| }) |
| } |
| } |
| } |
|
|
| if pe, ok := paddingEvasionFinding(f, "script-other"); ok { |
| out = append(out, pe) |
| } |
| return dedupeFindings(out), nil |
| } |
|
|