From 7befc337769b63cee608cfd5556636c572892242 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 29 Aug 2023 18:52:36 -0400 Subject: [PATCH 1/3] Add failing test cases Relates: https://github.com/elastic/go-libaudit/issues/127 https://github.com/elastic/go-libaudit/issues/71 --- aucoalesce/testdata/issue-127.yaml | 7 +++++++ aucoalesce/testdata/issue-71.yaml | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 aucoalesce/testdata/issue-127.yaml create mode 100644 aucoalesce/testdata/issue-71.yaml diff --git a/aucoalesce/testdata/issue-127.yaml b/aucoalesce/testdata/issue-127.yaml new file mode 100644 index 0000000..c2ebb38 --- /dev/null +++ b/aucoalesce/testdata/issue-127.yaml @@ -0,0 +1,7 @@ +--- + +tests: + multiple_avc_messages: | + type=AVC msg=audit(1668179838.476:649407): avc: denied { search } for pid=4059486 comm="cephcsi" name="crypto" dev="proc" ino=475090959 scontext=system_u:system_r:svirt_lxc_net_t:s0:c222,c955 tcontext=system_u:object_r:sysctl_crypto_t:s0 tclass=dir permissive=1 + type=AVC msg=audit(1668179838.476:649407): avc: denied { read } for pid=4059486 comm="cephcsi" name="fips_enabled" dev="proc" ino=475090960 scontext=system_u:system_r:svirt_lxc_net_t:s0:c222,c955 tcontext=system_u:object_r:sysctl_crypto_t:s0 tclass=file permissive=1 + type=AVC msg=audit(1668179838.476:649407): avc: denied { open } for pid=4059486 comm="cephcsi" path="/proc/sys/crypto/fips_enabled" dev="proc" ino=475090960 scontext=system_u:system_r:svirt_lxc_net_t:s0:c222,c955 tcontext=system_u:object_r:sysctl_crypto_t:s0 tclass=file permissive=1 diff --git a/aucoalesce/testdata/issue-71.yaml b/aucoalesce/testdata/issue-71.yaml new file mode 100644 index 0000000..ab0d2aa --- /dev/null +++ b/aucoalesce/testdata/issue-71.yaml @@ -0,0 +1,8 @@ +--- + +tests: + multiple_netfilter_cfg_messages: | + type=NETFILTER_CFG msg=audit(1593786232.477:31): table=filter family=2 entries=0 + type=NETFILTER_CFG msg=audit(1593786232.477:31): table=filter family=10 entries=0 + type=SYSCALL msg=audit(1593786232.477:31): arch=c000003e syscall=272 success=yes exit=0 a0=40000000 a1=7fffd2436fb0 a2=40000040 a3=22 items=0 ppid=1 pid=769 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="(ostnamed)" exe="/usr/lib/systemd/systemd" subj=system_u:system_r:init_t:s0 key=(null) + type=PROCTITLE msg=audit(1593786232.477:31): proctitle="(ostnamed)" From 478eaa0d8b51ef0f3e6388b4dd8e1d3b30d31465 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 29 Aug 2023 18:55:28 -0400 Subject: [PATCH 2/3] hack: remove syscall message requirement A syscall message should not be a hard requirement. Still left to be addressed is how to pass through the data from multiple AVC and NETFILTER_CFG messages. --- aucoalesce/coalesce.go | 8 +-- aucoalesce/testdata/issue-127.json.golden | 84 ++++++++++++++++++++++ aucoalesce/testdata/issue-71.json.golden | 87 +++++++++++++++++++++++ 3 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 aucoalesce/testdata/issue-127.json.golden create mode 100644 aucoalesce/testdata/issue-71.json.golden diff --git a/aucoalesce/coalesce.go b/aucoalesce/coalesce.go index 2857f5d..46b1eee 100644 --- a/aucoalesce/coalesce.go +++ b/aucoalesce/coalesce.go @@ -218,10 +218,10 @@ func normalizeCompound(msgs []*auparse.AuditMessage) (*Event, error) { break } } - if syscall == nil { - // All compound records have syscall messages. - return nil, errors.New("missing syscall message in compound event") - } + //if syscall == nil { + // // All compound records have syscall messages. + // return nil, errors.New("missing syscall message in compound event") + //} event := newEvent(special, syscall) diff --git a/aucoalesce/testdata/issue-127.json.golden b/aucoalesce/testdata/issue-127.json.golden new file mode 100644 index 0000000..e5f7ae1 --- /dev/null +++ b/aucoalesce/testdata/issue-127.json.golden @@ -0,0 +1,84 @@ +[ + { + "test_name": "multiple_avc_messages", + "event": { + "@timestamp": "2022-11-11T15:17:18.476Z", + "sequence": 649407, + "category": "mac-decision", + "record_type": "avc", + "result": "unknown", + "session": "", + "summary": { + "actor": { + "primary": "system_u:system_r:svirt_lxc_net_t:s0:c222,c955" + }, + "action": "violated-selinux-policy", + "object": { + "primary": "system_u:object_r:sysctl_crypto_t:s0", + "secondary": "dir" + }, + "how": "cephcsi" + }, + "user": {}, + "process": { + "pid": "4059486", + "name": "cephcsi" + }, + "data": { + "dev": "proc", + "ino": "475090959", + "name": "crypto", + "path": "/proc/sys/crypto/fips_enabled", + "permissive": "1", + "scontext": "system_u:system_r:svirt_lxc_net_t:s0:c222,c955", + "seperms": "search", + "seresult": "denied", + "tclass": "dir", + "tcontext": "system_u:object_r:sysctl_crypto_t:s0" + }, + "ecs": { + "event": {}, + "user": { + "effective": {}, + "target": {}, + "changes": {} + }, + "group": {} + } + }, + "warnings": [ + "duplicate key (comm) from AVC message", + "duplicate key (comm) from AVC message", + "duplicate key (comm) from AVC message", + "duplicate key (dev) from AVC message", + "duplicate key (dev) from AVC message", + "duplicate key (dev) from AVC message", + "duplicate key (ino) from AVC message", + "duplicate key (ino) from AVC message", + "duplicate key (ino) from AVC message", + "duplicate key (name) from AVC message", + "duplicate key (name) from AVC message", + "duplicate key (permissive) from AVC message", + "duplicate key (permissive) from AVC message", + "duplicate key (permissive) from AVC message", + "duplicate key (pid) from AVC message", + "duplicate key (pid) from AVC message", + "duplicate key (pid) from AVC message", + "duplicate key (scontext) from AVC message", + "duplicate key (scontext) from AVC message", + "duplicate key (scontext) from AVC message", + "duplicate key (seperms) from AVC message", + "duplicate key (seperms) from AVC message", + "duplicate key (seperms) from AVC message", + "duplicate key (seresult) from AVC message", + "duplicate key (seresult) from AVC message", + "duplicate key (seresult) from AVC message", + "duplicate key (tclass) from AVC message", + "duplicate key (tclass) from AVC message", + "duplicate key (tclass) from AVC message", + "duplicate key (tcontext) from AVC message", + "duplicate key (tcontext) from AVC message", + "duplicate key (tcontext) from AVC message" + ] + } +] diff --git a/aucoalesce/testdata/issue-71.json.golden b/aucoalesce/testdata/issue-71.json.golden new file mode 100644 index 0000000..0db11e8 --- /dev/null +++ b/aucoalesce/testdata/issue-71.json.golden @@ -0,0 +1,87 @@ +[ + { + "test_name": "multiple_netfilter_cfg_messages", + "event": { + "@timestamp": "2020-07-03T14:23:52.477Z", + "sequence": 31, + "category": "configuration", + "record_type": "netfilter_cfg", + "result": "success", + "session": "unset", + "summary": { + "actor": { + "primary": "unset", + "secondary": "0" + }, + "action": "loaded-firewall-rule-to", + "object": { + "type": "firewall", + "primary": "filter" + }, + "how": "/usr/lib/systemd/systemd" + }, + "user": { + "ids": { + "auid": "unset", + "egid": "0", + "euid": "0", + "fsgid": "0", + "fsuid": "0", + "gid": "0", + "sgid": "0", + "suid": "0", + "uid": "0" + }, + "selinux": { + "domain": "init_t", + "level": "s0", + "role": "system_r", + "user": "system_u" + } + }, + "process": { + "pid": "769", + "ppid": "1", + "title": "(ostnamed)", + "name": "(ostnamed)", + "exe": "/usr/lib/systemd/systemd" + }, + "data": { + "a0": "40000000", + "a1": "7fffd2436fb0", + "a2": "40000040", + "a3": "22", + "arch": "x86_64", + "entries": "0", + "exit": "0", + "family": "2", + "syscall": "unshare", + "table": "filter", + "tty": "(none)" + }, + "ecs": { + "event": { + "category": [ + "configuration", + "process" + ], + "type": [ + "change", + "info" + ] + }, + "user": { + "effective": {}, + "target": {}, + "changes": {} + }, + "group": {} + } + }, + "warnings": [ + "duplicate key (entries) from NETFILTER_CFG message", + "duplicate key (family) from NETFILTER_CFG message", + "duplicate key (table) from NETFILTER_CFG message" + ] + } +] From 0b9c9a9cf4d26d3f386db56df10223114b929a68 Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Fri, 8 Sep 2023 09:26:35 +0930 Subject: [PATCH 3/3] handle duplicate keys and AVC/NETFILTER_CFG events --- aucoalesce/coalesce.go | 79 ++++++++++++++++--- aucoalesce/testdata/issue-127.json.golden | 74 +++++++++-------- aucoalesce/testdata/issue-71.json.golden | 17 +++- .../ubuntu-16.04-linux-4.13.0.json.golden | 43 ++++++---- .../ubuntu-21.10-linux-5.13.json.golden | 3 - 5 files changed, 152 insertions(+), 64 deletions(-) diff --git a/aucoalesce/coalesce.go b/aucoalesce/coalesce.go index 46b1eee..29cc4b5 100644 --- a/aucoalesce/coalesce.go +++ b/aucoalesce/coalesce.go @@ -77,8 +77,10 @@ type Event struct { Dest *Address `json:"destination,omitempty" yaml:"destination,omitempty"` Net *Network `json:"network,omitempty" yaml:"network,omitempty"` - Data map[string]string `json:"data,omitempty" yaml:"data,omitempty"` - Paths []map[string]string `json:"paths,omitempty" yaml:"paths,omitempty"` + Data map[string]string `json:"data,omitempty" yaml:"data,omitempty"` + AVCData []map[string]string `json:"avc_data,omitempty" yaml:"avc_data,omitempty"` + NetfilterCFGData []map[string]string `json:"netfilter_cfg_data,omitempty" yaml:"netfilter_cfg_data,omitempty"` + Paths []map[string]string `json:"paths,omitempty" yaml:"paths,omitempty"` ECS ECSFields `json:"ecs" yaml:"ecs"` @@ -218,13 +220,21 @@ func normalizeCompound(msgs []*auparse.AuditMessage) (*Event, error) { break } } - //if syscall == nil { - // // All compound records have syscall messages. - // return nil, errors.New("missing syscall message in compound event") - //} event := newEvent(special, syscall) + keyCollision := false + seen := make(map[string]bool) + for _, msg := range msgs { + switch msg.RecordType { + case auparse.AUDIT_AVC, auparse.AUDIT_NETFILTER_CFG: + if hasKeyCollision(msg, seen) { + keyCollision = true + } + } + } + + dups := make(map[string]bool) for _, msg := range msgs { switch msg.RecordType { case auparse.AUDIT_SYSCALL: @@ -235,10 +245,23 @@ func normalizeCompound(msgs []*auparse.AuditMessage) (*Event, error) { addSockaddrRecord(msg, event) case auparse.AUDIT_EXECVE: addExecveRecord(msg, event) + case auparse.AUDIT_AVC: + if keyCollision { + addAVCRecord(msg, event) + } + addFieldsToEventData(msg, event, true, dups) + case auparse.AUDIT_NETFILTER_CFG: + if keyCollision { + addNetfilterCfgRecord(msg, event) + } + addFieldsToEventData(msg, event, true, dups) default: - addFieldsToEventData(msg, event) + addFieldsToEventData(msg, event, false, dups) } } + for k := range dups { + delete(event.Data, k) + } return event, nil } @@ -378,6 +401,43 @@ func addPathRecord(path *auparse.AuditMessage, event *Event) { event.Paths = append(event.Paths, data) } +func hasKeyCollision(msg *auparse.AuditMessage, seen map[string]bool) bool { + data, err := msg.Data() + if err != nil { + return false + } + + for k := range data { + if seen[k] { + return true + } + seen[k] = true + } + return false +} + +func addAVCRecord(path *auparse.AuditMessage, event *Event) { + data, err := path.Data() + if err != nil { + event.Warnings = append(event.Warnings, fmt.Errorf( + "failed to parse AVC message: %w", err)) + return + } + + event.AVCData = append(event.AVCData, data) +} + +func addNetfilterCfgRecord(path *auparse.AuditMessage, event *Event) { + data, err := path.Data() + if err != nil { + event.Warnings = append(event.Warnings, fmt.Errorf( + "failed to parse NETFILTER_CFG message: %w", err)) + return + } + + event.NetfilterCFGData = append(event.NetfilterCFGData, data) +} + func addProcess(event *Event) { event.Process.PID = event.Data["pid"] delete(event.Data, "pid") @@ -434,7 +494,7 @@ func addExecveRecord(execve *auparse.AuditMessage, event *Event) { event.Process.Args = args } -func addFieldsToEventData(msg *auparse.AuditMessage, event *Event) { +func addFieldsToEventData(msg *auparse.AuditMessage, event *Event, allowDuplicate bool, dups map[string]bool) { data, err := msg.Data() if err != nil { event.Warnings = append(event.Warnings, @@ -443,9 +503,10 @@ func addFieldsToEventData(msg *auparse.AuditMessage, event *Event) { } for k, v := range data { - if _, found := event.Data[k]; found { + if o, found := event.Data[k]; found && (o != v || !allowDuplicate) { event.Warnings = append(event.Warnings, fmt.Errorf( "duplicate key (%v) from %v message", k, msg.RecordType)) + dups[k] = true continue } event.Data[k] = v diff --git a/aucoalesce/testdata/issue-127.json.golden b/aucoalesce/testdata/issue-127.json.golden index e5f7ae1..661414b 100644 --- a/aucoalesce/testdata/issue-127.json.golden +++ b/aucoalesce/testdata/issue-127.json.golden @@ -14,8 +14,7 @@ }, "action": "violated-selinux-policy", "object": { - "primary": "system_u:object_r:sysctl_crypto_t:s0", - "secondary": "dir" + "primary": "system_u:object_r:sysctl_crypto_t:s0" }, "how": "cephcsi" }, @@ -26,16 +25,53 @@ }, "data": { "dev": "proc", - "ino": "475090959", - "name": "crypto", "path": "/proc/sys/crypto/fips_enabled", "permissive": "1", "scontext": "system_u:system_r:svirt_lxc_net_t:s0:c222,c955", - "seperms": "search", "seresult": "denied", - "tclass": "dir", "tcontext": "system_u:object_r:sysctl_crypto_t:s0" }, + "avc_data": [ + { + "comm": "cephcsi", + "dev": "proc", + "ino": "475090959", + "name": "crypto", + "permissive": "1", + "pid": "4059486", + "scontext": "system_u:system_r:svirt_lxc_net_t:s0:c222,c955", + "seperms": "search", + "seresult": "denied", + "tclass": "dir", + "tcontext": "system_u:object_r:sysctl_crypto_t:s0" + }, + { + "comm": "cephcsi", + "dev": "proc", + "ino": "475090960", + "name": "fips_enabled", + "permissive": "1", + "pid": "4059486", + "scontext": "system_u:system_r:svirt_lxc_net_t:s0:c222,c955", + "seperms": "read", + "seresult": "denied", + "tclass": "file", + "tcontext": "system_u:object_r:sysctl_crypto_t:s0" + }, + { + "comm": "cephcsi", + "dev": "proc", + "ino": "475090960", + "path": "/proc/sys/crypto/fips_enabled", + "permissive": "1", + "pid": "4059486", + "scontext": "system_u:system_r:svirt_lxc_net_t:s0:c222,c955", + "seperms": "open", + "seresult": "denied", + "tclass": "file", + "tcontext": "system_u:object_r:sysctl_crypto_t:s0" + } + ], "ecs": { "event": {}, "user": { @@ -47,38 +83,14 @@ } }, "warnings": [ - "duplicate key (comm) from AVC message", - "duplicate key (comm) from AVC message", - "duplicate key (comm) from AVC message", - "duplicate key (dev) from AVC message", - "duplicate key (dev) from AVC message", - "duplicate key (dev) from AVC message", - "duplicate key (ino) from AVC message", "duplicate key (ino) from AVC message", "duplicate key (ino) from AVC message", "duplicate key (name) from AVC message", - "duplicate key (name) from AVC message", - "duplicate key (permissive) from AVC message", - "duplicate key (permissive) from AVC message", - "duplicate key (permissive) from AVC message", - "duplicate key (pid) from AVC message", - "duplicate key (pid) from AVC message", - "duplicate key (pid) from AVC message", - "duplicate key (scontext) from AVC message", - "duplicate key (scontext) from AVC message", - "duplicate key (scontext) from AVC message", - "duplicate key (seperms) from AVC message", "duplicate key (seperms) from AVC message", "duplicate key (seperms) from AVC message", - "duplicate key (seresult) from AVC message", - "duplicate key (seresult) from AVC message", - "duplicate key (seresult) from AVC message", - "duplicate key (tclass) from AVC message", "duplicate key (tclass) from AVC message", "duplicate key (tclass) from AVC message", - "duplicate key (tcontext) from AVC message", - "duplicate key (tcontext) from AVC message", - "duplicate key (tcontext) from AVC message" + "failed to set object secondary using keys=[tclass] because they were not found" ] } ] diff --git a/aucoalesce/testdata/issue-71.json.golden b/aucoalesce/testdata/issue-71.json.golden index 0db11e8..12e4cbc 100644 --- a/aucoalesce/testdata/issue-71.json.golden +++ b/aucoalesce/testdata/issue-71.json.golden @@ -54,11 +54,22 @@ "arch": "x86_64", "entries": "0", "exit": "0", - "family": "2", "syscall": "unshare", "table": "filter", "tty": "(none)" }, + "netfilter_cfg_data": [ + { + "entries": "0", + "family": "2", + "table": "filter" + }, + { + "entries": "0", + "family": "10", + "table": "filter" + } + ], "ecs": { "event": { "category": [ @@ -79,9 +90,7 @@ } }, "warnings": [ - "duplicate key (entries) from NETFILTER_CFG message", - "duplicate key (family) from NETFILTER_CFG message", - "duplicate key (table) from NETFILTER_CFG message" + "duplicate key (family) from NETFILTER_CFG message" ] } ] diff --git a/aucoalesce/testdata/ubuntu-16.04-linux-4.13.0.json.golden b/aucoalesce/testdata/ubuntu-16.04-linux-4.13.0.json.golden index 86c55ab..a0376d8 100644 --- a/aucoalesce/testdata/ubuntu-16.04-linux-4.13.0.json.golden +++ b/aucoalesce/testdata/ubuntu-16.04-linux-4.13.0.json.golden @@ -73,11 +73,7 @@ }, "group": {} } - }, - "warnings": [ - "duplicate key (comm) from AVC message", - "duplicate key (pid) from AVC message" - ] + } }, { "test_name": "AVC_AppArmor_unlink", @@ -131,7 +127,6 @@ "arch": "x86_64", "exit": "0", "fsuid": "100", - "name": "/var/lib/apt/lists/partial/.apt-acquire-privs-test.zW4jyj", "operation": "unlink", "ouid": "100", "profile": "docker-nginx", @@ -139,6 +134,30 @@ "syscall": "unlink", "tty": "pts0" }, + "avc_data": [ + { + "apparmor": "AUDIT", + "comm": "apt-get", + "fsuid": "100", + "name": "/var/lib/apt/lists/partial/.apt-acquire-privs-test.zW4jyj", + "operation": "unlink", + "ouid": "100", + "pid": "26024", + "profile": "docker-nginx", + "requested_mask": "d" + }, + { + "apparmor": "AUDIT", + "comm": "apt-get", + "fsuid": "100", + "name": "/var/lib/docker/aufs/diff/8087092ad17fa7433455dccab4f52b438ae032d22bf40a8d098c7235cfad53d8/var/lib/apt/lists/partial/.apt-acquire-privs-test.zW4jyj", + "operation": "unlink", + "ouid": "100", + "pid": "26024", + "profile": "docker-nginx", + "requested_mask": "d" + } + ], "paths": [ { "cap_fe": "0", @@ -203,17 +222,7 @@ } }, "warnings": [ - "duplicate key (apparmor) from AVC message", - "duplicate key (comm) from AVC message", - "duplicate key (comm) from AVC message", - "duplicate key (fsuid) from AVC message", - "duplicate key (name) from AVC message", - "duplicate key (operation) from AVC message", - "duplicate key (ouid) from AVC message", - "duplicate key (pid) from AVC message", - "duplicate key (pid) from AVC message", - "duplicate key (profile) from AVC message", - "duplicate key (requested_mask) from AVC message" + "duplicate key (name) from AVC message" ] } ] diff --git a/aucoalesce/testdata/ubuntu-21.10-linux-5.13.json.golden b/aucoalesce/testdata/ubuntu-21.10-linux-5.13.json.golden index 3a47670..92570c4 100644 --- a/aucoalesce/testdata/ubuntu-21.10-linux-5.13.json.golden +++ b/aucoalesce/testdata/ubuntu-21.10-linux-5.13.json.golden @@ -206,9 +206,6 @@ "a3": "7ffe952bd080", "arch": "x86_64", "exit": "5", - "new": "142290059264000", - "old": "61699325952000", - "op": "freq", "syscall": "clock_adjtime", "tty": "(none)" },