내 손으로 뚫고 막는다 — 쿠버네티스 보안 10대 과제 CTF를 만들며
“내 클러스터가 진짜 안전한가?“라는 질문에는 문서를 아무리 읽어도 자신 있게 답하기 어렵습니다. RBAC 개념을 안다는 것과, 와일드카드 권한을 실제로 손에 쥐고 kubectl get secrets로 플래그를 훔쳐본 경험은 완전히 다른 층위의 이해이기 때문입니다. 그래서 Docs의 보안 섹션에 이론(Concept)과 실습(Hands-on)만으로는 채워지지 않는 한 조각, 공격자가 되어 침투하고 다시 방어자로 돌아와 패치하는 CTF(Capture The Flag) 미션 10개를 추가했습니다.
왜 뚫어보는 게 먼저인가
쿠버네티스 보안 사고의 대다수는 “몰라서"가 아니라 기본값을 그대로 쓰거나, 여러 방어선 중 하나만 잠그고 나머지를 방치해서 일어납니다. securityContext 하나 빠뜨린 것, RBAC에 박아둔 * 하나, 환경 변수에 그대로 적어둔 비밀번호 하나 — 글로 읽을 때는 사소해 보이지만, 그 설정이 없을 때 실제로 무엇이 뚫리는지 직접 겪어보면 다시는 잊히지 않습니다.
그래서 OWASP Kubernetes Top 10 (2025) 기준을 뼈대로 삼아 가상의 이커머스 기업 NimbusMart의 취약한 클러스터를 배경으로, 각 미션을 “취약한 설정 → 침투 → 패치 → 재검증"의 사이클로 구성했습니다.
10개 미션이 그리는 지도
| 단계 | 미션 | 무엇을 배우는가 |
|---|---|---|
| 1~3 | K01 Insecure Workload · K02 Authorization · K03 Secrets | 컨테이너 실행, 권한, 정보 관리 — 기본기 |
| 4~6 | K04 Policy Enforcement · K05 Network Segmentation · K06 Exposed Components | 정책, 네트워크, 외부 노출 관리 — 방어선 구축 |
| 7~10 | K07 Cluster Components · K08 Cluster to Cloud · K09 Authentication · K10 Logging & Monitoring | 컴포넌트 보안, 클라우드 연동, 인증, 기록 — 운영 보안 |
기획하면서 의도적으로 지킨 원칙이 하나 있습니다. 앞 단계가 뚫리는 이유를 뒷 단계가 이어받도록 설계한 것입니다. K01에서 컨테이너 내부 권한을 최소화해도, K02에서 RBAC이 와일드카드면 결국 API 서버 자체가 뚫립니다. K02를 좁혀도 K03처럼 비밀번호가 평문으로 널려 있으면 그 좁은 권한만으로도 충분히 털립니다. 하나의 레이어만 완벽한 보안은 존재하지 않는다는 걸, 순서대로 밟아보면 몸으로 느끼게 됩니다.
가장 기억에 남는 세 장면
K01 — Read-only file system이 뜨는 순간. securityContext 없이 띄운 Pod에 접속해 whoami를 치면 root가 나오고, touch /test.txt도 그냥 됩니다. runAsNonRoot와 readOnlyRootFilesystem만 추가했을 뿐인데, 똑같은 명령이 Read-only file system 에러로 막힙니다. 설정 네 줄의 무게가 이렇게 크다는 걸 코드로 보여줄 때가 가장 설득력이 있었습니다.
K03 — describe pod 한 번으로 끝나는 게임. env.value에 비밀번호를 박아두면 kubectl describe pod만으로 그대로 노출됩니다. Secret 참조로 바꾸면 화면에는 <set to the key 'password' in secret 'db-secret'>라는 레퍼런스만 남고, 실제 값을 보려면 별도의 RBAC 권한이 또 필요해집니다. K02(권한)와 K03(비밀 관리)이 서로를 지탱하는 구조라는 걸 가장 잘 보여주는 미션입니다.
K08 — 169.254.169.254라는 숫자. 클라우드 위에서 도는 Pod는 기본적으로 메타데이터 서비스에 접근할 수 있고, 여기엔 노드의 IAM 임시 토큰이 그대로 담겨 있습니다. Pod 하나만 뚫려도 클러스터를 넘어 클라우드 계정 자체가 위험해질 수 있다는 걸 curl 한 줄로 확인하는 순간, “쿠버네티스 보안"의 경계가 클러스터 안에서 끝나지 않는다는 걸 체감했습니다.
Docs와의 관계
블로그를 운영하는 방식에서 밝힌 원칙대로, 이 글은 1차 기록이고 정제된 지식은 Docs의 CTF 미션 페이지에 남겼습니다. 각 미션 페이지에는 vulnerable.yaml/fixed.yaml 비교, 실제 침투·방어 명령어, 체크리스트까지 실려 있어서 실습 환경만 있으면 바로 손으로 따라 할 수 있습니다.
이론으로 “RBAC은 최소 권한이어야 한다"를 아는 것과, verbs: ["*"]로 뚫린 뒤 verbs: ["get", "list"]로 막아본 것은 다른 종류의 지식입니다. 결국 보안은 책보다, 한 번 뚫어보고 막아보는 경험에서 더 오래 남습니다.