chainguard-dev / malcontent

detect malicious program behaviors
Apache License 2.0
407 stars 26 forks source link

Add support for rule overrides; ignore "false_positive" and "ignore" tags by default #473

Open egibs opened 2 hours ago

egibs commented 2 hours ago

Closes #471

We've wanted to support rule overrides for a while. This PR attempts to do so in a basic way by storing matched rules in a map (both the original and the override should match) and then dropping the original rule if an override exists. For now, we'll allow for severity overrides and then store the combined descriptions of the two rules for later display.

For example,

This YARA:

rule send {
    meta:
        description = "send a message to a socket"
        ref = "https://linux.die.net/man/2/send"
        syscall = "send"
    strings:
        $send = "send" fullword
        $socket = "socket" fullword
    condition:
        all of them
}

rule send_override {
    meta:
        description = "this overrides the send rule"
        ref = "https://linux.die.net/man/2/send"
        syscall = "send"
    strings:
        $send = "send" fullword
        $socket = "socket" fullword
    condition:
        all of them
}

Results in this output:

$ go run . analyze out/samples-84a2015439ad84d3005fa57d06d7a925acb9f2a3/javascript/clean/connection.js
out/samples-84a2015439ad84d3005fa57d06d7a925acb9f2a3/javascript/clean/connection.js [⚠️ MEDIUM]
---------------------------------------------------------------------------------------------------------------------------------
RISK  KEY                         DESCRIPTION                                        EVIDENCE
---------------------------------------------------------------------------------------------------------------------------------
LOW   encoding/base64             Supports base64 encoded strings                    base64
LOW   fd/write                    writes to a file handle                            outgoingMessageStream.write(message)
LOW   net/dns                     Uses DNS (Domain Name Service)                     require("dns")
LOW   net/socket/send             this overrides the send rule, send a message to a  send
                                  socket                                             socket
LOW   ref/site/url                contains embedded HTTPS URLs                       https://github.com/pekim/tedious/issues/24
LOW   ref/words/password          references a 'password'                            UsernamePasswordCredential
                                                                                     directory-password
MED   data/embedded/base64/terms  Contains base64 content                            FkZHJlc3::$address
                                                                                     RpcmVjdG9ye::$directory
                                                                                     YWRkcmVzc::$address
                                                                                     ZGlyZWN0b3J5::$directory
                                                                                     aHRtb::$html
                                                                                     hZGRyZXNz::$address
                                                                                     kaXJlY3Rvcn::$directory
MED   data/embedded/base64/url    Contains base64 url                                aHR0cDovL::$http
                                                                                     h0dHA6Ly::$http
                                                                                     h0dHBzOi8v::$https
                                                                                     odHRwOi8v::$http
                                                                                     odHRwczovL::$https
MED   evasion/hex                 converts hex data to ASCII                         toString('hex');
---------------------------------------------------------------------------------------------------------------------------------

The important part:

LOW   net/socket/send             this overrides the send rule, send a message to a  send
                                  socket                                             socket

Severity overrides also work:

rule send_override : critical {
    meta:
        description = "send a message to a socket but critical"
        ref = "https://linux.die.net/man/2/send"
        syscall = "send"
    strings:
        $send = "send" fullword
        $socket = "socket" fullword
    condition:
        all of them
}

⬇️

go run . analyze out/samples-84a2015439ad84d3005fa57d06d7a925acb9f2a3/javascript/clean/connection.js
out/samples-84a2015439ad84d3005fa57d06d7a925acb9f2a3/javascript/clean/connection.js [🚨 CRITICAL]
-------------------------------------------------------------------------------------------------------------------------------
RISK  KEY                         DESCRIPTION                                      EVIDENCE
-------------------------------------------------------------------------------------------------------------------------------
LOW   encoding/base64             Supports base64 encoded strings                  base64
LOW   fd/write                    writes to a file handle                          outgoingMessageStream.write(message)
LOW   net/dns                     Uses DNS (Domain Name Service)                   require("dns")
LOW   ref/site/url                contains embedded HTTPS URLs                     https://github.com/pekim/tedious/issues/24
LOW   ref/words/password          references a 'password'                          UsernamePasswordCredential
                                                                                   directory-password
MED   data/embedded/base64/terms  Contains base64 content                          FkZHJlc3::$address
                                                                                   RpcmVjdG9ye::$directory
                                                                                   YWRkcmVzc::$address
                                                                                   ZGlyZWN0b3J5::$directory
                                                                                   aHRtb::$html
                                                                                   hZGRyZXNz::$address
                                                                                   kaXJlY3Rvcn::$directory
MED   data/embedded/base64/url    Contains base64 url                              aHR0cDovL::$http
                                                                                   h0dHA6Ly::$http
                                                                                   h0dHBzOi8v::$https
                                                                                   odHRwOi8v::$http
                                                                                   odHRwczovL::$https
MED   evasion/hex                 converts hex data to ASCII                       toString('hex');
CRIT  net/socket/send             send a message to a socket but critical, send a  send
                                  message to a socket                              socket
-------------------------------------------------------------------------------------------------------------------------------

Additionally, we'll now filter out false_positive and ignore tags by default.

Given:

rule send : ignore {
    meta:
        description = "send a message to a socket"
        ref = "https://linux.die.net/man/2/send"
        syscall = "send"
    strings:
        $send = "send" fullword
        $socket = "socket" fullword
    condition:
        all of them
}

or:

rule send : false_positive {
    meta:
        description = "send a message to a socket"
        ref = "https://linux.die.net/man/2/send"
        syscall = "send"
    strings:
        $send = "send" fullword
        $socket = "socket" fullword
    condition:
        all of them
}

The output will no longer contain that match:

$ go run . analyze out/samples-84a2015439ad84d3005fa57d06d7a925acb9f2a3/javascript/clean/connection.js
out/samples-84a2015439ad84d3005fa57d06d7a925acb9f2a3/javascript/clean/connection.js [⚠️ MEDIUM]
---------------------------------------------------------------------------------------------------------------
RISK  KEY                         DESCRIPTION                      EVIDENCE
---------------------------------------------------------------------------------------------------------------
LOW   encoding/base64             Supports base64 encoded strings  base64
LOW   fd/write                    writes to a file handle          outgoingMessageStream.write(message)
LOW   net/dns                     Uses DNS (Domain Name Service)   require("dns")
LOW   ref/site/url                contains embedded HTTPS URLs     https://github.com/pekim/tedious/issues/24
LOW   ref/words/password          references a 'password'          UsernamePasswordCredential
                                                                   directory-password
MED   data/embedded/base64/terms  Contains base64 content          FkZHJlc3::$address
                                                                   RpcmVjdG9ye::$directory
                                                                   YWRkcmVzc::$address
                                                                   ZGlyZWN0b3J5::$directory
                                                                   aHRtb::$html
                                                                   hZGRyZXNz::$address
                                                                   kaXJlY3Rvcn::$directory
MED   data/embedded/base64/url    Contains base64 url              aHR0cDovL::$http
                                                                   h0dHA6Ly::$http
                                                                   h0dHBzOi8v::$https
                                                                   odHRwOi8v::$http
                                                                   odHRwczovL::$https
MED   evasion/hex                 converts hex data to ASCII       toString('hex');
---------------------------------------------------------------------------------------------------------------