mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-03-12 21:22:57 -07:00
Add content from: nodes/proxy GET → Kubelet /exec RCE via WebSocket handshake ...
This commit is contained in:
@@ -677,7 +677,26 @@ Principals with access to the **`nodes/proxy`** subresource can **execute code o
|
||||
../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md
|
||||
{{#endref}}
|
||||
|
||||
You have an example of how to get [**RCE talking authorized to a Kubelet API here**](../pentesting-kubernetes-services/index.html#kubelet-rce).
|
||||
#### nodes/proxy GET -> Kubelet /exec via WebSocket verb confusion
|
||||
|
||||
- Kubelet maps HTTP methods to RBAC verbs **before** protocol upgrade. WebSocket handshakes must start with **HTTP GET** (`Connection: Upgrade`), so `/exec` over WebSocket is checked as **verb `get`** instead of the expected `create`.
|
||||
- `/exec`, `/run`, `/attach`, and `/portforward` are not explicitly mapped and fall into the default **`proxy`** subresource, so the authorization question becomes **`can <user> get nodes/proxy?`**
|
||||
- If a token only has **`nodes/proxy` + `get`**, direct WebSocket access to the kubelet on `https://<node_ip>:10250` allows arbitrary command execution in any pod on that node. The same request via the API server proxy path (`/api/v1/nodes/<node>/proxy/exec/...`) is denied because it is a normal HTTP POST and maps to `create`.
|
||||
- The kubelet performs no second authorization after the WebSocket upgrade; only the initial GET is evaluated.
|
||||
|
||||
**Direct exploit (requires network reachability to the kubelet and a token with `nodes/proxy` GET):**
|
||||
|
||||
```bash
|
||||
kubectl auth can-i --list | grep "nodes/proxy"
|
||||
websocat --insecure \
|
||||
--header "Authorization: Bearer $TOKEN" \
|
||||
--protocol "v4.channel.k8s.io" \
|
||||
"wss://$NODE_IP:10250/exec/$NAMESPACE/$POD/$CONTAINER?output=1&error=1&command=id"
|
||||
```
|
||||
|
||||
- Use the **Node IP**, not the node name. The same request with `curl -X POST` will be **Forbidden** because it maps to `create`.
|
||||
- Direct kubelet access bypasses the API server, so AuditPolicy only shows `subjectaccessreviews` from the kubelet user agent and **does not log `pods/exec`** commands.
|
||||
- Enumerate affected service accounts with the [detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a) to find tokens limited to `nodes/proxy` GET.
|
||||
|
||||
### Delete pods + unschedulable nodes
|
||||
|
||||
@@ -844,6 +863,9 @@ https://github.com/aquasecurity/kube-bench
|
||||
- [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers)
|
||||
- [**https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html**](https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html)
|
||||
- [**https://kubenomicon.com/**](https://kubenomicon.com/)
|
||||
- [nodes/proxy GET -> kubelet exec WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce)
|
||||
- [nodes/proxy GET detection script](https://gist.github.com/grahamhelton/f5c8ce265161990b0847ac05a74e466a)
|
||||
- [websocat](https://github.com/vi/websocat)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
@@ -91,6 +91,9 @@ The kubelet authorizes API requests using the same [request attributes](https://
|
||||
| /spec/\* | nodes | spec |
|
||||
| _all others_ | nodes | proxy |
|
||||
|
||||
> [!NOTE]
|
||||
> WebSocket-based `/exec`, `/run`, `/attach`, and `/portforward` fall into the default **proxy** subresource and are authorized using the initial HTTP **GET** handshake. A principal with only `nodes/proxy` **GET** can still exec containers if it connects directly to `https://<node_ip>:10250` over WebSockets. See the [nodes/proxy GET -> Kubelet /exec verb confusion abuse](../abusing-roles-clusterroles-in-kubernetes/README.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion) for details.
|
||||
|
||||
For example, the following request tried to access the pods info of kubelet without permission:
|
||||
|
||||
```bash
|
||||
@@ -105,6 +108,7 @@ Forbidden (user=system:node:ip-172-31-28-172.ec2.internal, verb=get, resource=no
|
||||
## References
|
||||
|
||||
- [https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
|
||||
- [nodes/proxy GET -> kubelet exec via WebSocket bypass](https://grahamhelton.com/blog/nodes-proxy-rce)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user