본문으로 건너뛰기
K02: Authorization — 과도한 RBAC 권한

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를 생성할 수 있었습니다. 해결된 코드에서는 이것이 원천적으로 불가능합니다. resourcesverbs를 각각 얼마나 좁히느냐가 침투 이후의 피해 반경(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"

권한을 podsget/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 자체를 어떻게 안전하게 보관할지를 다룹니다.