Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/action/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func scanSinglePath(ctx context.Context, c malcontent.Config, path string, ruleF
return fr, nil
}

fr, err := report.Generate(ctx, path, mrs, c, archiveRoot, logger, fc)
fr, err := report.Generate(ctx, path, mrs, c, archiveRoot, logger, fc, kind)
if err != nil {
return nil, NewFileReportError(err, path, TypeGenerateError)
}
Expand Down
23 changes: 17 additions & 6 deletions pkg/action/testdata/scan_archive
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,17 @@
"ID": "c2/client",
"RuleName": "clientID"
},
{
"Description": "contains Cloudflare DNS resolver IP",
"MatchStrings": [
"1.1.1.1"
],
"RiskScore": 2,
"RiskLevel": "MEDIUM",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/discovery/ip-dns_resolver.yara#cloudflare_dns_ip",
"ID": "c2/discovery/ip_dns_resolver",
"RuleName": "cloudflare_dns_ip"
},
{
"Description": "references a specific architecture",
"MatchStrings": [
Expand Down Expand Up @@ -1070,15 +1081,15 @@
"RuleName": "go_file_read"
},
{
"Description": "renames files",
"Description": "rename",
Comment thread
egibs marked this conversation as resolved.
Outdated
"MatchStrings": [
"os.rename"
"rename"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/file/file-rename.yara#explicit_rename",
"RiskScore": 0,
"RiskLevel": "NONE",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/file/file-rename.yara#rename",
"ID": "fs/file/rename",
"RuleName": "explicit_rename"
"RuleName": "rename"
},
{
"Description": "access filesystem metadata",
Expand Down
152 changes: 152 additions & 0 deletions pkg/action/testdata/scan_oci
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,158 @@
"SHA256": "",
"Size": 0,
"RiskScore": 0
},
"/var/lib/db/sbom/ca-certificates-bundle-20240705-r0.spdx.json": {
"Path": "testdata/static.tar.xz ∴ /var/lib/db/sbom/ca-certificates-bundle-20240705-r0.spdx.json",
"SHA256": "da392082c5abe93e62ac6b557fd1dae8aedb16851c76a8b0b942235c4f24fcf2",
"Size": 1768,
"Behaviors": [
{
"Description": "references a specific architecture",
"MatchStrings": [
"https://",
"x86_64"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/tool_transfer/arch.yara#arch_ref",
"ID": "c2/tool_transfer/arch",
"RuleName": "arch_ref"
},
{
"Description": "references a specific operating system",
"MatchStrings": [
"https://",
"linux"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/tool_transfer/os.yara#os_ref",
"ID": "c2/tool_transfer/os",
"RuleName": "os_ref"
},
{
"Description": "download files",
"MatchStrings": [
"downloadLocation"
],
"RiskScore": 2,
"RiskLevel": "MEDIUM",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/download/download.yara#download",
"ID": "net/download",
"RuleName": "download"
},
{
"Description": "contains embedded HTTPS URLs",
"MatchStrings": [
"https://spdx.org/spdxdocs/chainguard/melange/e8bb6c0f7fc0c77fe29111695575"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url/embedded.yara#https_url",
"ID": "net/url/embedded",
"RuleName": "https_url"
}
],
"RiskScore": 2,
"RiskLevel": "MEDIUM"
},
"/var/lib/db/sbom/tzdata-2024b-r0.spdx.json": {
"Path": "testdata/static.tar.xz ∴ /var/lib/db/sbom/tzdata-2024b-r0.spdx.json",
"SHA256": "d30d9bc94854359f6e4164fca583b5a51e1a6625c7e8b4b0563364e676a5bcaf",
"Size": 1725,
"Behaviors": [
{
"Description": "references a specific architecture",
"MatchStrings": [
"https://",
"x86_64"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/tool_transfer/arch.yara#arch_ref",
"ID": "c2/tool_transfer/arch",
"RuleName": "arch_ref"
},
{
"Description": "download files",
"MatchStrings": [
"downloadLocation"
],
"RiskScore": 2,
"RiskLevel": "MEDIUM",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/download/download.yara#download",
"ID": "net/download",
"RuleName": "download"
},
{
"Description": "contains embedded HTTPS URLs",
"MatchStrings": [
"https://spdx.org/spdxdocs/chainguard/melange/7b86e6ff94c1f8dfe207a3ffaf7f"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url/embedded.yara#https_url",
"ID": "net/url/embedded",
"RuleName": "https_url"
},
{
"Description": "Uses timezone information",
"MatchStrings": [
"tzdata"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/os/time/tzinfo.yara#tzinfo",
"ID": "os/time/tzinfo",
"RuleName": "tzinfo"
}
],
"RiskScore": 2,
"RiskLevel": "MEDIUM"
},
"/var/lib/db/sbom/wolfi-baselayout-20230201-r15.spdx.json": {
"Path": "testdata/static.tar.xz ∴ /var/lib/db/sbom/wolfi-baselayout-20230201-r15.spdx.json",
"SHA256": "2553d473dbfb8842254573d68cd3e857b2e9546fb746d8ae7fc3c243c9eca8ca",
"Size": 1425,
"Behaviors": [
{
"Description": "references a specific architecture",
"MatchStrings": [
"https://",
"x86_64"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/c2/tool_transfer/arch.yara#arch_ref",
"ID": "c2/tool_transfer/arch",
"RuleName": "arch_ref"
},
{
"Description": "download files",
"MatchStrings": [
"downloadLocation"
],
"RiskScore": 2,
"RiskLevel": "MEDIUM",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/download/download.yara#download",
"ID": "net/download",
"RuleName": "download"
},
{
"Description": "contains embedded HTTPS URLs",
"MatchStrings": [
"https://spdx.org/spdxdocs/chainguard/melange/568a7518ce6c3bdb5ddcf51a311c"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url/embedded.yara#https_url",
"ID": "net/url/embedded",
"RuleName": "https_url"
}
],
"RiskScore": 2,
"RiskLevel": "MEDIUM"
}
}
}
4 changes: 4 additions & 0 deletions pkg/programkind/programkind.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,17 @@ var supportedKind = map[string]string{
"h": "text/x-h",
"hh": "text/x-h",
"html": "",
"jar": "application/java-archive",
"java": "text/x-java",
"js": "application/javascript",
"json": "application/json",
"ko": "application/x-object",
"lnk": "application/x-ms-shortcut",
"lua": "text/x-lua",
"macho": "application/x-mach-binary",
"md": "",
"o": "application/octet-stream",
"pe": "application/vnd.microsoft.portable-executable",
"php": "text/x-php",
"pl": "text/x-perl",
"pm": "text/x-script.perl-module",
Expand Down
2 changes: 1 addition & 1 deletion pkg/programkind/programkind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestPath(t *testing.T) {
{"/etc/systemd/system/launcher.service", &FileType{MIME: "text/x-systemd", Ext: "service"}},
{"yarn-package.json", &FileType{MIME: "application/json", Ext: "json"}},
{"/home/yeti/.hidden/package.json", &FileType{MIME: "application/json", Ext: "json"}},
{"unknown.json", nil},
{"unknown.json", &FileType{MIME: "application/json", Ext: "json"}},
}
for _, tt := range tests {
t.Run(tt.in, func(t *testing.T) {
Expand Down
19 changes: 18 additions & 1 deletion pkg/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

"github.com/chainguard-dev/clog"
"github.com/chainguard-dev/malcontent/pkg/malcontent"
"github.com/chainguard-dev/malcontent/pkg/programkind"

yarax "github.com/VirusTotal/yara-x/go"
)
Expand Down Expand Up @@ -364,8 +365,20 @@ func TrimPrefixes(path string, prefixes []string) string {
return path
}

// fileMatchesRules checks the scanned file's type against a rule's defined filetypes.
func fileMatchesRule(meta []yarax.Metadata, mime string) bool {
for _, m := range meta {
if m.Identifier() == "filetypes" {
filetypes := strings.Split(fmt.Sprintf("%s", m.Value()), ",")
return slices.Contains(filetypes, mime)
}
}
// Rules without filetype metadata are universal
return true
}

//nolint:cyclop // ignore complexity of 64
func Generate(ctx context.Context, path string, mrs *yarax.ScanResults, c malcontent.Config, expath string, _ *clog.Logger, fc []byte) (*malcontent.FileReport, error) {
func Generate(ctx context.Context, path string, mrs *yarax.ScanResults, c malcontent.Config, expath string, _ *clog.Logger, fc []byte, kind *programkind.FileType) (*malcontent.FileReport, error) {
if ctx.Err() != nil {
return &malcontent.FileReport{}, ctx.Err()
}
Expand Down Expand Up @@ -425,6 +438,10 @@ func Generate(ctx context.Context, path string, mrs *yarax.ScanResults, c malcon
ignoreMalcontent = true
}

if !fileMatchesRule(m.Metadata(), kind.MIME) {
continue
}

override := slices.Contains(m.Tags(), "override")

risk = behaviorRisk(m.Namespace(), m.Identifier(), m.Tags())
Expand Down
1 change: 1 addition & 0 deletions rules/anti-behavior/LD_DEBUG.yara
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
rule env_LD_DEBUG: medium {
meta:
description = "may check if dynamic linker debugging is enabled"
filetypes = "application/x-elf,application/x-mach-binary"

strings:
$val = "LD_DEBUG" fullword
Expand Down
1 change: 1 addition & 0 deletions rules/anti-behavior/LD_PROFILE.yara
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
rule env_LD_PROFILE: medium {
meta:
description = "may check if dynamic linker profiling is enabled"
filetypes = "application/x-elf,application/x-mach-binary"

strings:
$val = "LD_PROFILE" fullword
Expand Down
3 changes: 3 additions & 0 deletions rules/anti-behavior/anti-debugger.yara
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
rule win_debugger_present: medium windows {
meta:
description = "Detects if process is being executed within a debugger"
filetypes = "text/x-powershell,application/octet-stream,application/vnd.microsoft.portable-executable"

strings:
$debug_idp = "IsDebuggerPresent"
Expand All @@ -13,6 +14,7 @@ rule win_debugger_present: medium windows {
rule win_debugger_or_vm: medium windows {
meta:
description = "Detects if process is being executed within a debugger or VM"
filetypes = "text/x-powershell,application/octet-stream,application/vnd.microsoft.portable-executable"

strings:
$cpu_pfp = "IsProcessorFeaturePresent"
Expand All @@ -27,6 +29,7 @@ rule win_debugger_or_vm: medium windows {
rule multiple_linux_methods: high linux {
meta:
description = "possible debugger detection across multiple methods"
filetypes = "application/x-elf"

strings:
$ld_profile = "LD_PROFILE" fullword
Expand Down
3 changes: 3 additions & 0 deletions rules/anti-behavior/process-check.yara
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
rule activity_monitor_checker: high macos {
meta:
description = "checks if 'Activity Monitor' is running"
filetypes = "application/x-mach-binary"

strings:
$ps = "ps" fullword
Expand All @@ -16,6 +17,7 @@ rule activity_monitor_checker: high macos {
rule linux_monitors: high linux {
meta:
description = "checks if various process monitors are running"
filetypes = "application/x-elf"

strings:
$pgrep = "pgrep" fullword
Expand Down Expand Up @@ -45,6 +47,7 @@ rule linux_monitors: high linux {
rule anti_rootkit_hunter: high linux {
meta:
description = "checks if rootkit detectors are running"
filetypes = "application/x-elf"

strings:
$proc = "/proc/"
Expand Down
3 changes: 3 additions & 0 deletions rules/anti-behavior/random_behavior.yara
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ private rule random_behavior_pythonSetup {
rule setuptools_random: critical {
meta:
description = "Python library installer that exhibits random behavior"
filetypes = "text/x-python"

strings:
$ref = "import random"
Expand All @@ -32,6 +33,7 @@ rule setuptools_random: critical {
rule java_random: low {
meta:
description = "exhibits random behavior"
filetypes = "text/x-java"

strings:
$ref = "java/util/Random"
Expand All @@ -43,6 +45,7 @@ rule java_random: low {
rule rand_call: medium {
meta:
description = "exhibits random behavior"
filetypes = "text/x-c,text/x-php,text/x-perl"
Comment thread
egibs marked this conversation as resolved.
Outdated

strings:
$ref = "rand()"
Expand Down
Loading
Loading