Skip to content

Commit 80f1aaa

Browse files
roikolrafaeldtinoco
authored andcommitted
signature: add default_loader_modification.go sig
1 parent ab1f7b1 commit 80f1aaa

File tree

3 files changed

+307
-0
lines changed

3 files changed

+307
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
7+
"github.com/aquasecurity/tracee/signatures/helpers"
8+
"github.com/aquasecurity/tracee/types/detect"
9+
"github.com/aquasecurity/tracee/types/protocol"
10+
"github.com/aquasecurity/tracee/types/trace"
11+
)
12+
13+
type DefaultLoaderModification struct {
14+
cb detect.SignatureHandler
15+
dynamicLoaderPattern string
16+
compiledRegex *regexp.Regexp
17+
}
18+
19+
func (sig *DefaultLoaderModification) Init(cb detect.SignatureHandler) error {
20+
var err error
21+
sig.cb = cb
22+
sig.dynamicLoaderPattern = "^\\/(lib|usr\\/lib).*\\/ld.*\\.so[^\\/]*"
23+
sig.compiledRegex, err = regexp.Compile(sig.dynamicLoaderPattern)
24+
return err
25+
}
26+
27+
func (sig *DefaultLoaderModification) GetMetadata() (detect.SignatureMetadata, error) {
28+
return detect.SignatureMetadata{
29+
ID: "TRC-169",
30+
Version: "1",
31+
Name: "Default dynamic loader modification detected",
32+
Description: "The default dynamic loader has been modified. The dynamic loader is an executable file loaded to process memory and run before the executable to load dynamic libraries to the process. An attacker might use this technique to hijack the execution context of each new process and bypass defenses.",
33+
Properties: map[string]interface{}{
34+
"Severity": 3,
35+
"Category": "defense-evasion",
36+
"Technique": "Hijack Execution Flow",
37+
"Kubernetes_Technique": "",
38+
"id": "attack-pattern--aedfca76-3b30-4866-b2aa-0f1d7fd1e4b6",
39+
"external_id": "T1574",
40+
},
41+
}, nil
42+
}
43+
44+
func (sig *DefaultLoaderModification) GetSelectedEvents() ([]detect.SignatureEventSelector, error) {
45+
return []detect.SignatureEventSelector{
46+
{Source: "tracee", Name: "security_file_open", Origin: "*"},
47+
{Source: "tracee", Name: "security_inode_rename", Origin: "*"},
48+
}, nil
49+
}
50+
51+
func (sig *DefaultLoaderModification) OnEvent(event protocol.Event) error {
52+
53+
eventObj, ok := event.Payload.(trace.Event)
54+
if !ok {
55+
return fmt.Errorf("invalid event")
56+
}
57+
58+
path := ""
59+
60+
switch eventObj.EventName {
61+
62+
case "security_file_open":
63+
64+
flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags")
65+
if err != nil {
66+
return err
67+
}
68+
69+
if helpers.IsFileWrite(flags) {
70+
pathname, err := helpers.GetTraceeStringArgumentByName(eventObj, "pathname")
71+
if err != nil {
72+
return err
73+
}
74+
75+
path = pathname
76+
}
77+
78+
case "security_inode_rename":
79+
newPath, err := helpers.GetTraceeStringArgumentByName(eventObj, "new_path")
80+
if err != nil {
81+
return err
82+
}
83+
84+
path = newPath
85+
}
86+
87+
if sig.compiledRegex.MatchString(path) {
88+
metadata, err := sig.GetMetadata()
89+
if err != nil {
90+
return err
91+
}
92+
sig.cb(detect.Finding{
93+
SigMetadata: metadata,
94+
Event: event,
95+
Data: nil,
96+
})
97+
}
98+
99+
return nil
100+
}
101+
102+
func (sig *DefaultLoaderModification) OnSignal(s detect.Signal) error {
103+
return nil
104+
}
105+
func (sig *DefaultLoaderModification) Close() {}
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package main
2+
3+
import (
4+
"testing"
5+
6+
"github.com/aquasecurity/tracee/signatures/signaturestest"
7+
"github.com/aquasecurity/tracee/types/detect"
8+
"github.com/aquasecurity/tracee/types/trace"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestDefaultLoaderModification(t *testing.T) {
14+
testCases := []struct {
15+
Name string
16+
Events []trace.Event
17+
Findings map[string]detect.Finding
18+
}{
19+
{
20+
Name: "should trigger detection - security_file_open",
21+
Events: []trace.Event{
22+
{
23+
EventName: "security_file_open",
24+
Args: []trace.Argument{
25+
{
26+
ArgMeta: trace.ArgMeta{
27+
Name: "pathname",
28+
},
29+
Value: interface{}("/usr/lib/x86_64-linux-gnu/ld-2.31.so"),
30+
},
31+
{
32+
ArgMeta: trace.ArgMeta{
33+
Name: "flags",
34+
},
35+
Value: interface{}("O_WRONLY"),
36+
},
37+
},
38+
},
39+
},
40+
Findings: map[string]detect.Finding{
41+
"TRC-169": {
42+
Data: nil,
43+
Event: trace.Event{
44+
EventName: "security_file_open",
45+
Args: []trace.Argument{
46+
{
47+
ArgMeta: trace.ArgMeta{
48+
Name: "pathname",
49+
},
50+
Value: interface{}("/usr/lib/x86_64-linux-gnu/ld-2.31.so"),
51+
},
52+
{
53+
ArgMeta: trace.ArgMeta{
54+
Name: "flags",
55+
},
56+
Value: interface{}("O_WRONLY"),
57+
},
58+
},
59+
}.ToProtocol(),
60+
SigMetadata: detect.SignatureMetadata{
61+
ID: "TRC-169",
62+
Version: "1",
63+
Name: "Default dynamic loader modification detected",
64+
Description: "The default dynamic loader has been modified. The dynamic loader is an executable file loaded to process memory and run before the executable to load dynamic libraries to the process. An attacker might use this technique to hijack the execution context of each new process and bypass defenses.",
65+
Properties: map[string]interface{}{
66+
"Severity": 3,
67+
"Category": "defense-evasion",
68+
"Technique": "Hijack Execution Flow",
69+
"Kubernetes_Technique": "",
70+
"id": "attack-pattern--aedfca76-3b30-4866-b2aa-0f1d7fd1e4b6",
71+
"external_id": "T1574",
72+
},
73+
},
74+
},
75+
},
76+
},
77+
{
78+
Name: "should trigger detection - security_inode_rename",
79+
Events: []trace.Event{
80+
{
81+
EventName: "security_inode_rename",
82+
Args: []trace.Argument{
83+
{
84+
ArgMeta: trace.ArgMeta{
85+
Name: "new_path",
86+
},
87+
Value: interface{}("/usr/lib/x86_64-linux-gnu/ld-2.31.so"),
88+
},
89+
},
90+
},
91+
},
92+
Findings: map[string]detect.Finding{
93+
"TRC-169": {
94+
Data: nil,
95+
Event: trace.Event{
96+
EventName: "security_inode_rename",
97+
Args: []trace.Argument{
98+
{
99+
ArgMeta: trace.ArgMeta{
100+
Name: "new_path",
101+
},
102+
Value: interface{}("/usr/lib/x86_64-linux-gnu/ld-2.31.so"),
103+
},
104+
},
105+
}.ToProtocol(),
106+
SigMetadata: detect.SignatureMetadata{
107+
ID: "TRC-169",
108+
Version: "1",
109+
Name: "Default dynamic loader modification detected",
110+
Description: "The default dynamic loader has been modified. The dynamic loader is an executable file loaded to process memory and run before the executable to load dynamic libraries to the process. An attacker might use this technique to hijack the execution context of each new process and bypass defenses.",
111+
Properties: map[string]interface{}{
112+
"Severity": 3,
113+
"Category": "defense-evasion",
114+
"Technique": "Hijack Execution Flow",
115+
"Kubernetes_Technique": "",
116+
"id": "attack-pattern--aedfca76-3b30-4866-b2aa-0f1d7fd1e4b6",
117+
"external_id": "T1574",
118+
},
119+
},
120+
},
121+
},
122+
},
123+
{
124+
Name: "should not trigger detection - security_file_open wrong open flags",
125+
Events: []trace.Event{
126+
{
127+
EventName: "security_file_open",
128+
Args: []trace.Argument{
129+
{
130+
ArgMeta: trace.ArgMeta{
131+
Name: "pathname",
132+
},
133+
Value: interface{}("/usr/lib/x86_64-linux-gnu/ld-2.31.so"),
134+
},
135+
{
136+
ArgMeta: trace.ArgMeta{
137+
Name: "flags",
138+
},
139+
Value: interface{}("O_RDONLY"),
140+
},
141+
},
142+
},
143+
},
144+
Findings: map[string]detect.Finding{},
145+
},
146+
{
147+
Name: "should not trigger detection - security_file_open wrong path",
148+
Events: []trace.Event{
149+
{
150+
EventName: "security_file_open",
151+
Args: []trace.Argument{
152+
{
153+
ArgMeta: trace.ArgMeta{
154+
Name: "pathname",
155+
},
156+
Value: interface{}("/tmp/something"),
157+
},
158+
{
159+
ArgMeta: trace.ArgMeta{
160+
Name: "flags",
161+
},
162+
Value: interface{}("O_WRONLY"),
163+
},
164+
},
165+
},
166+
},
167+
Findings: map[string]detect.Finding{},
168+
},
169+
{
170+
Name: "should not trigger detection - security_inode_rename wrong path",
171+
Events: []trace.Event{
172+
{
173+
EventName: "security_inode_rename",
174+
Args: []trace.Argument{
175+
{
176+
ArgMeta: trace.ArgMeta{
177+
Name: "new_path",
178+
},
179+
Value: interface{}("/tmp/something"),
180+
},
181+
},
182+
},
183+
},
184+
Findings: map[string]detect.Finding{},
185+
},
186+
}
187+
188+
for _, tc := range testCases {
189+
t.Run(tc.Name, func(t *testing.T) {
190+
holder := signaturestest.FindingsHolder{}
191+
sig := DefaultLoaderModification{}
192+
sig.Init(holder.OnFinding)
193+
194+
for _, e := range tc.Events {
195+
err := sig.OnEvent(e.ToProtocol())
196+
require.NoError(t, err)
197+
}
198+
assert.Equal(t, tc.Findings, holder.GroupBySigID())
199+
})
200+
}
201+
}

signatures/golang/export.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ var ExportedSignatures = []detect.Signature{
1414
&ScheduledTaskModification{},
1515
&LdPreload{},
1616
&CgroupNotifyOnReleaseModification{},
17+
&DefaultLoaderModification{},
1718
}

0 commit comments

Comments
 (0)