Skip to content

Commit 08e363e

Browse files
roikolrafaeldtinoco
authored andcommitted
signature: add kubernetes_certificate_theft_attempt.go sig
1 parent 40fc0cd commit 08e363e

File tree

3 files changed

+343
-0
lines changed

3 files changed

+343
-0
lines changed

signatures/golang/export.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ var ExportedSignatures = []detect.Signature{
3232
&FilelessExecution{},
3333
&IllegitimateShell{},
3434
&KernelModuleLoading{},
35+
&KubernetesCertificateTheftAttempt{},
3536
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strings"
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 KubernetesCertificateTheftAttempt struct {
14+
cb detect.SignatureHandler
15+
legitProcs []string
16+
k8sCertificatesDir string
17+
}
18+
19+
func (sig *KubernetesCertificateTheftAttempt) Init(cb detect.SignatureHandler) error {
20+
sig.cb = cb
21+
sig.legitProcs = []string{"kube-apiserver", "kubelet", "kube-controller", "etcd"}
22+
sig.k8sCertificatesDir = "/etc/kubernetes/pki/"
23+
return nil
24+
}
25+
26+
func (sig *KubernetesCertificateTheftAttempt) GetMetadata() (detect.SignatureMetadata, error) {
27+
return detect.SignatureMetadata{
28+
ID: "TRC-35",
29+
Version: "1",
30+
Name: "K8s TLS certificate theft detected",
31+
Description: "Theft of Kubernetes TLS certificates was detected. TLS certificates are used to establish trust between systems. The Kubernetes certificate is used to to enable secure communication between Kubernetes components, such as kubelet scheduler controller and API Server. An adversary may steal a Kubernetes certificate on a compromised system to impersonate Kubernetes components within the cluster.",
32+
Properties: map[string]interface{}{
33+
"Severity": 3,
34+
"Category": "credential-access",
35+
"Technique": "Steal Application Access Token",
36+
"Kubernetes_Technique": "",
37+
"id": "attack-pattern--890c9858-598c-401d-a4d5-c67ebcdd703a",
38+
"external_id": "T1528",
39+
},
40+
}, nil
41+
}
42+
43+
func (sig *KubernetesCertificateTheftAttempt) GetSelectedEvents() ([]detect.SignatureEventSelector, error) {
44+
return []detect.SignatureEventSelector{
45+
{Source: "tracee", Name: "security_file_open", Origin: "*"},
46+
{Source: "tracee", Name: "security_inode_rename", Origin: "*"},
47+
}, nil
48+
}
49+
50+
func (sig *KubernetesCertificateTheftAttempt) OnEvent(event protocol.Event) error {
51+
52+
eventObj, ok := event.Payload.(trace.Event)
53+
if !ok {
54+
return fmt.Errorf("invalid event")
55+
}
56+
57+
path := ""
58+
59+
switch eventObj.EventName {
60+
61+
case "security_file_open":
62+
63+
// check process touching certificate is not on allow list
64+
for _, legitProc := range sig.legitProcs {
65+
if legitProc == eventObj.ProcessName {
66+
return nil
67+
}
68+
}
69+
70+
flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags")
71+
if err != nil {
72+
return err
73+
}
74+
75+
if helpers.IsFileRead(flags) {
76+
pathname, err := helpers.GetTraceeStringArgumentByName(eventObj, "pathname")
77+
if err != nil {
78+
return err
79+
}
80+
81+
path = pathname
82+
}
83+
84+
case "security_inode_rename":
85+
86+
oldPath, err := helpers.GetTraceeStringArgumentByName(eventObj, "old_path")
87+
if err != nil {
88+
return err
89+
}
90+
91+
path = oldPath
92+
93+
}
94+
95+
if strings.HasPrefix(path, sig.k8sCertificatesDir) {
96+
metadata, err := sig.GetMetadata()
97+
if err != nil {
98+
return err
99+
}
100+
sig.cb(detect.Finding{
101+
SigMetadata: metadata,
102+
Event: event,
103+
Data: nil,
104+
})
105+
}
106+
107+
return nil
108+
}
109+
110+
func (sig *KubernetesCertificateTheftAttempt) OnSignal(s detect.Signal) error {
111+
return nil
112+
}
113+
func (sig *KubernetesCertificateTheftAttempt) Close() {}
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
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 TestKubernetesCertificateTheftAttempt(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+
ProcessName: "malware",
24+
EventName: "security_file_open",
25+
Args: []trace.Argument{
26+
{
27+
ArgMeta: trace.ArgMeta{
28+
Name: "flags",
29+
},
30+
Value: interface{}("O_RDONLY"),
31+
},
32+
{
33+
ArgMeta: trace.ArgMeta{
34+
Name: "pathname",
35+
},
36+
Value: interface{}("/etc/kubernetes/pki/ca.crt"),
37+
},
38+
},
39+
},
40+
},
41+
Findings: map[string]detect.Finding{
42+
"TRC-35": {
43+
Data: nil,
44+
Event: trace.Event{
45+
ProcessName: "malware",
46+
EventName: "security_file_open",
47+
Args: []trace.Argument{
48+
{
49+
ArgMeta: trace.ArgMeta{
50+
Name: "flags",
51+
},
52+
Value: interface{}("O_RDONLY"),
53+
},
54+
{
55+
ArgMeta: trace.ArgMeta{
56+
Name: "pathname",
57+
},
58+
Value: interface{}("/etc/kubernetes/pki/ca.crt"),
59+
},
60+
},
61+
}.ToProtocol(),
62+
SigMetadata: detect.SignatureMetadata{
63+
ID: "TRC-35",
64+
Version: "1",
65+
Name: "K8s TLS certificate theft detected",
66+
Description: "Theft of Kubernetes TLS certificates was detected. TLS certificates are used to establish trust between systems. The Kubernetes certificate is used to to enable secure communication between Kubernetes components, such as kubelet scheduler controller and API Server. An adversary may steal a Kubernetes certificate on a compromised system to impersonate Kubernetes components within the cluster.",
67+
Properties: map[string]interface{}{
68+
"Severity": 3,
69+
"Category": "credential-access",
70+
"Technique": "Steal Application Access Token",
71+
"Kubernetes_Technique": "",
72+
"id": "attack-pattern--890c9858-598c-401d-a4d5-c67ebcdd703a",
73+
"external_id": "T1528",
74+
},
75+
},
76+
},
77+
},
78+
},
79+
{
80+
Name: "should trigger detection - security_inode_rename",
81+
Events: []trace.Event{
82+
{
83+
EventName: "security_inode_rename",
84+
Args: []trace.Argument{
85+
{
86+
ArgMeta: trace.ArgMeta{
87+
Name: "old_path",
88+
},
89+
Value: interface{}("/etc/kubernetes/pki/ca.crt"),
90+
},
91+
},
92+
},
93+
},
94+
Findings: map[string]detect.Finding{
95+
"TRC-35": {
96+
Data: nil,
97+
Event: trace.Event{
98+
EventName: "security_inode_rename",
99+
Args: []trace.Argument{
100+
{
101+
ArgMeta: trace.ArgMeta{
102+
Name: "old_path",
103+
},
104+
Value: interface{}("/etc/kubernetes/pki/ca.crt"),
105+
},
106+
},
107+
}.ToProtocol(),
108+
SigMetadata: detect.SignatureMetadata{
109+
ID: "TRC-35",
110+
Version: "1",
111+
Name: "K8s TLS certificate theft detected",
112+
Description: "Theft of Kubernetes TLS certificates was detected. TLS certificates are used to establish trust between systems. The Kubernetes certificate is used to to enable secure communication between Kubernetes components, such as kubelet scheduler controller and API Server. An adversary may steal a Kubernetes certificate on a compromised system to impersonate Kubernetes components within the cluster.",
113+
Properties: map[string]interface{}{
114+
"Severity": 3,
115+
"Category": "credential-access",
116+
"Technique": "Steal Application Access Token",
117+
"Kubernetes_Technique": "",
118+
"id": "attack-pattern--890c9858-598c-401d-a4d5-c67ebcdd703a",
119+
"external_id": "T1528",
120+
},
121+
},
122+
},
123+
},
124+
},
125+
{
126+
Name: "should not trigger detection - security_file_open wrong open flags",
127+
Events: []trace.Event{
128+
{
129+
ProcessName: "test",
130+
EventName: "security_file_open",
131+
Args: []trace.Argument{
132+
{
133+
ArgMeta: trace.ArgMeta{
134+
Name: "flags",
135+
},
136+
Value: interface{}("O_WRONLY"),
137+
},
138+
{
139+
ArgMeta: trace.ArgMeta{
140+
Name: "pathname",
141+
},
142+
Value: interface{}("/etc/kubernetes/pki/ca.crt"),
143+
},
144+
},
145+
},
146+
},
147+
Findings: map[string]detect.Finding{},
148+
},
149+
{
150+
Name: "should not trigger detection - security_file_open wrong path",
151+
Events: []trace.Event{
152+
{
153+
ProcessName: "test",
154+
EventName: "security_file_open",
155+
Args: []trace.Argument{
156+
{
157+
ArgMeta: trace.ArgMeta{
158+
Name: "flags",
159+
},
160+
Value: interface{}("O_RDONLY"),
161+
},
162+
{
163+
ArgMeta: trace.ArgMeta{
164+
Name: "pathname",
165+
},
166+
Value: interface{}("/tmp/ca.crt"),
167+
},
168+
},
169+
},
170+
},
171+
Findings: map[string]detect.Finding{},
172+
},
173+
{
174+
Name: "should not trigger detection - security_file_open legit proc",
175+
Events: []trace.Event{
176+
{
177+
ProcessName: "kube-apiserver",
178+
EventName: "security_file_open",
179+
Args: []trace.Argument{
180+
{
181+
ArgMeta: trace.ArgMeta{
182+
Name: "flags",
183+
},
184+
Value: interface{}("O_RDONLY"),
185+
},
186+
{
187+
ArgMeta: trace.ArgMeta{
188+
Name: "pathname",
189+
},
190+
Value: interface{}("/etc/kubernetes/pki/ca.crt"),
191+
},
192+
},
193+
},
194+
},
195+
Findings: map[string]detect.Finding{},
196+
},
197+
{
198+
Name: "should not trigger detection - security_inode_rename wrong path",
199+
Events: []trace.Event{
200+
{
201+
EventName: "security_inode_rename",
202+
Args: []trace.Argument{
203+
{
204+
ArgMeta: trace.ArgMeta{
205+
Name: "old_path",
206+
},
207+
Value: interface{}("/tmp/ca.crt"),
208+
},
209+
},
210+
},
211+
},
212+
Findings: map[string]detect.Finding{},
213+
},
214+
}
215+
216+
for _, tc := range testCases {
217+
t.Run(tc.Name, func(t *testing.T) {
218+
holder := signaturestest.FindingsHolder{}
219+
sig := KubernetesCertificateTheftAttempt{}
220+
sig.Init(holder.OnFinding)
221+
222+
for _, e := range tc.Events {
223+
err := sig.OnEvent(e.ToProtocol())
224+
require.NoError(t, err)
225+
}
226+
assert.Equal(t, tc.Findings, holder.GroupBySigID())
227+
})
228+
}
229+
}

0 commit comments

Comments
 (0)