K02: Authorization — 과도한 RBAC 권한
쿠버네티스에서 RBAC(Role-Based Access Control)은 “누가 무엇을 할 수 있는가"를 정의합니다. 취약한 설정은 공격자가 이 권한을 악용해 관리자 수준의 정보를 탈취하거나 클러스터를 장악하게 만듭니다. Concept의 RBAC — 최소 권한의 단위에서 Role/RoleBinding 조합의 기본기를 다뤘다면, 여기서는 그 권한이 와일드카드로 남용됐을 때 실제로 무엇이 뚫리는지를 직접 확인합니다.
미션: 과도한 RBAC 권한 (Privilege Escalation)
1. 취약한 코드 (vulnerable.yaml)
공격자가 침투하기 좋은 전형적인 ‘와일드카드’ 설정입니다.
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pod-reader
rules:
- apiGroups: [""]
resources: ["*"] # 🚨 위험: 모든 리소스에 접근 가능
verbs: ["*"] # 🚨 위험: 모든 동작(생성, 수정, 삭제, 읽기) 수행 가능분석: 특정 리소스(예: pods)에만 권한을 줘야 하는데 *를 사용해서, 클러스터 내 거의 모든 데이터를 읽거나 조작할 수 있는 ‘과도한 권한’이 부여되어 있습니다. 공격자가 이 Role을 가진 Pod에 침투하면 클러스터 전체를 장악할 수 있습니다.
2. 해결책 코드 (fixed.yaml)
‘최소 권한의 원칙’에 따라 필요한 최소한의 권한만 허용합니다.
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"] # ✅ 개선: 오직 'pods' 리소스만 접근
verbs: ["get", "list"] # ✅ 개선: 읽기(get, list) 권한만 허용| 설정 | 취약한 버전 | 안전한 버전 | 막는 대상 |
|---|---|---|---|
resources | ["*"] | ["pods"] | Secret, ConfigMap 등 다른 리소스까지 접근하는 것 |
verbs | ["*"] | ["get", "list"] | delete/create/update 등 쓰기·삭제 동작 |
왜 이 비교가 중요한가
취약한 코드에서는 verbs: ["*"] 덕분에 공격자가 delete로 서비스를 마비시키거나, create 권한으로 악성 Pod를 생성할 수 있었습니다. 해결된 코드에서는 이것이 원천적으로 불가능합니다. resources와 verbs를 각각 얼마나 좁히느냐가 침투 이후의 피해 반경(blast radius)을 결정합니다.
resources: ["*"]로 배포된 Role은 나중에 CRD가 추가되면 그 CRD에 대한 권한도 별도 승인 없이 자동으로 갖게 됩니다.실습: 공격 → 방어 검증
1) 공격 — 과도한 권한으로 정보 탈취
kubectl apply -f vulnerable.yaml
kubectl apply -f rolebinding.yaml
# 취약한 Role을 부여받은 ServiceAccount로 실행
kubectl get secrets --as=system:serviceaccount:default:pod-reader-sa
# 원래는 pods만 봐야 하는데 Secret까지 조회 가능 — 플래그(민감 정보) 탈취2) 방어 — 패치 적용 후 동일한 명령 재시도
kubectl apply -f fixed.yaml
kubectl get secrets --as=system:serviceaccount:default:pod-reader-sa
# Error from server (Forbidden): secrets is forbidden:
# User "system:serviceaccount:default:pod-reader-sa" cannot list resource "secrets"권한을 pods의 get/list로만 좁히자, 동일한 ServiceAccount로도 Forbidden이 발생합니다. 이 확인은 배포 후에도 권한 점검 명령의 kubectl auth can-i로 언제든 재현할 수 있습니다.
체크리스트
-
resources: ["*"]또는verbs: ["*"]로 정의된 Role/ClusterRole이 있는가 (kubectl get clusterroles -o json | jq로 점검) - 각 ServiceAccount가 실제로 필요한 리소스·동작만 부여받았는가
- 네임스페이스 경계를 넘지 않는 권한은 ClusterRole이 아니라 Role로 스코프를 좁혔는가
-
cluster-admin이 바인딩된 불필요한 ClusterRoleBinding이 남아있지 않은가
K01이 컨테이너 내부의 권한을 다뤘다면, K02는 클러스터 API에 대한 권한을 다뤘습니다. 다음 미션(K03: Secrets)에서는 그 권한으로 결국 노려지는 대상, 즉 Secret 자체를 어떻게 안전하게 보관할지를 다룹니다.