뉴스 목록
BleepingComputer2026. 09. 23.

Kubernetes YAML 파일 하나로 GCP 전체 조직을 넘겨줄 수 있는 방법

한 줄 요약

Kubernetes Config Connector(KCC)를 사용하는 GCP(Google Cloud Platform) 환경에서 'ConfigConfusion'이라는 권한 상승 취약점이 공개되었습니다. Kubernetes 클러스터의 특정 네임스페이스에 접근할 수 있는 공격자가 단 하나의 YAML 파일을 제출하는 것만으로 GCP 전체 조직의 최고 관리자 권한을 탈취할 수 있습니다. 이 문제는 Kubernetes의 접근 제어(RBAC)와 GCP의 권한 체계(IAM)가 서로 다른 부분만 검증하고, KCC가 제한된 권한을 가진 사용자의 요청을 자신의 조직 수준 권한으로 대신 실행하기 때문에 발생합니다. Google은 이를 설계대로 동작하는 것이라고 밝혀 패치 계획이 없으므로, KCC 네임스페이스 모드 사용·광범위한 IAM 역할 제거·IAMPolicyMember 리소스 생성 권한 제한 등 운영 환경 점검이 시급합니다.

사건

보안 연구자 Justin O'Leary가 공개한 ConfigConfusion 기법으로, GCP 클라우드 자격증명 없이 Kubernetes 네임스페이스 접근권한만으로 YAML 파일 하나를 제출해 GCP 전체 조직에 roles/owner 권한을 부여할 수 있음이 밝혀졌다.

영향

KCC가 조직 수준 IAM 권한을 보유한 환경에서는 제한된 Kubernetes 접근권한만 있으면 누구든 GCP 조직 전체 소유자 권한을 탈취할 수 있으며, Google Cloud 자격증명 없이 공격 가능하다.

원인

Kubernetes RBAC는 클러스터 내 리소스 생성 여부만 판단하고, GCP IAM은 KCC 서비스 계정의 권한만 확인한다. 두 시스템이 각각 절반씩만 검증하므로 KCC가 사용자 권한을 초과하는 작업을 대신 수행하는 '혼동된 대리인(confused deputy)' 문제가 발생한다.

대응

Google은 KCC가 설계대로 동작한다는 입장이며, 패치 대신 운영 설정 변경을 권고한다. KCC 네임스페이스 모드 도입, roles/owner 및 organizationAdmin 등 광범위한 IAM 역할 제거, IAMPolicyMember 리소스 생성 권한을 플랫폼 팀으로 제한, 조직·폴더 수준 IAM 변경 모니터링이 핵심 대응책이다.

실무 포인트

KCC 서비스 계정에 조직 수준의 광범위한 역할이 부여되어 있고, 일반 개발팀에게 IAMPolicyMember 리소스 생성 권한이 열려 있다면 즉시 점검이 필요하다. 두 조건이 동시에 충족될 경우 GCP 자격증명 없이 조직 전체가 탈취될 수 있다.

본문

개발자가 데이터베이스, 스토리지 버킷, 가상 머신과 같은 클라우드 리소스를 생성하려면 클라우드 공급자에 인증할 자격증명이 필요합니다. Google Cloud에서는 서비스 계정 키(service account key), 즉 사용자가 누구이며 어떤 작업을 할 수 있는지 증명하는 JSON 파일이 그 역할을 하는 경우가 많습니다.

서비스 계정 키의 문제는 그것이 파일이라는 점입니다. 파일은 복사되고, 이메일로 전송되고, 실수로 Git 저장소에 커밋되고, 노트북에 남겨진 채 잊혀집니다.

팀원이 퇴사하더라도 조직은 그 사람이 어떤 키를 가지고 있었는지 항상 파악하지 못합니다. 수십 명의 개발자에 걸쳐 자격증명을 추적하고 교체하는 작업은 상당한 운영 부담이자 보안 위험입니다.

업계에서는 이를 시크릿 스프롤(secret sprawl) 이라고 부릅니다. 감사하기 어렵고 제거하기는 더 어려운 방식으로 클라우드 자격증명이 기기, 파이프라인, 코드베이스 전반에 흩어지는 현상입니다.

GitOps가 자격증명을 제거하는 방법

Kubernetes 커뮤니티가 이 문제에 대해 내놓은 해법은 GitOps 오퍼레이터(컨트롤러라고도 함)입니다.

  1. 개발자는 필요한 리소스를 기술하는 YAML 설정 파일을 작성하고, Git에 커밋한 뒤 Kubernetes 클러스터에 적용합니다.
  2. 클러스터 내부에서 실행되는 컨트롤러가 이 파일을 읽고, 개발자를 대신해 클라우드 리소스를 생성하거나 업데이트합니다.

핵심은 이것입니다: 개발자는 클라우드 자격증명을 전혀 갖지 않아도 됩니다. 컨트롤러가 자체 자격증명을 사용해 개발자를 대신해 인증합니다.

Google의 이 시스템은 Google Kubernetes Config Connector(KCC)로, 일반적으로 Google Kubernetes Engine(GKE) 클러스터 내부에서 실행됩니다. KCC는 Google Cloud 리소스를 기술하는 설정 파일을 감시하고, 해당하는 Google Cloud API를 호출해 리소스를 생성하거나 업데이트합니다.

스토리지 버킷의 객체를 읽는 권한을 애플리케이션에 부여하려는 개발자는 IAMPolicyMember 리소스를 제출할 수 있습니다.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: my-binding
  namespace: my-team
spec:
  member: "serviceAccount:my-app@my-project.iam.gserviceaccount.com"
  role: roles/storage.objectViewer
  resourceRef:
    kind: Project
    external: "my-project"

KCC는 Workload Identity를 통해 Google Cloud에 인증하며, 플랫폼 팀이 관리하는 Google 서비스 계정(흔히 KCC GSA라 부름)을 사용합니다. KCC는 여러 프로젝트, 폴더, 또는 전체 조직에 걸쳐 인프라를 관리할 수 있으므로 이 계정에는 roles/owner 나 roles/resourcemanager.organizationAdmin 같은 광범위한 역할이 부여되는 경우가 많습니다.

개발자가 리소스를 제출하면 KCC가 이를 감지하고 Google Cloud IAM을 호출합니다. 권한이 생성되고, 개발자는 Google Cloud 자격증명을 한 번도 다루지 않습니다.

모든 네임스페이스는 KCC의 단일 조직 수준 아이덴티티를 공유합니다

이 구성은 원래 목적에 잘 부합합니다. 개발자 자격증명 불필요, 모든 것이 Git에 선언, 플랫폼 팀이 수십 개가 아닌 하나의 서비스 계정만 관리. 자격증명 스프롤 문제가 해결됩니다.

네임스페이스 접근권한이 조직 owner가 되는 순간

그러나 이 구성이 새로운 문제를 만들어냅니다.

KCC는 어느 Kubernetes 사용자가 리소스를 제출했는지와 무관하게 자체 서비스 계정을 통해 모든 Google Cloud 작업을 수행합니다. 그 계정에 조직 수준 권한이 있다면, 제한된 클러스터 접근권한을 가진 사용자도 그 권한을 간접적으로 행사할 수 있습니다. 이 기법을 보안 연구자 Justin O'Leary가 ConfigConfusion이라 명명했습니다.

공격자가 다음을 갖추고 있다면:

  1. KCC가 감시하는 Kubernetes 네임스페이스 접근권한
  2. 해당 네임스페이스에서 IAMPolicyMember 리소스를 생성할 수 있는 권한
  3. Google Cloud 자격증명이나 권한은 전혀 없음

KCC의 서비스 계정이 부여할 수 있는 어떤 Google Cloud IAM 역할이든 자신에게 부여할 수 있습니다. 전체 조직의 roles/owner 를 포함해서입니다.

공격 자체는 명령 하나입니다.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
 name: escalation
 namespace: my-team
spec:
 member: "serviceAccount:attacker@attacker-project.iam.gserviceaccount.com"
 role: roles/owner
 resourceRef:
 apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
 kind: Organization
 external: "123456789"

공격자가 Kubernetes를 통해 YAML을 적용합니다. KCC가 이를 읽고 자체 서비스 계정으로 Google Cloud에 IAM 변경을 요청합니다. 해당 서비스 계정은 이 변경을 수행할 권한이 있으므로 요청이 수락됩니다. 공격자는 Google Cloud 자격증명을 한 번도 보유하지 않은 채 Google Cloud 조직을 장악합니다.

IAMPolicyMember 하나로 네임스페이스 접근권한이 조직 소유권으로 바뀝니다

두 개의 인가 시스템, 하나의 누락된 검사

이것이 왜 작동하는지 이해하려면 요청을 처리하는 두 개의 별도 인가 시스템을 살펴봐야 합니다.

  1. Kubernetes RBAC 는 사용자가 클러스터 내에서 무엇을 할 수 있는지 제어합니다. "이 사용자가 이 네임스페이스에서 IAMPolicyMember 리소스를 생성할 수 있는가?"라고 묻습니다. 가능하다면 허용합니다. Google Cloud에 대해서는 아무것도 모르며, 그 리소스가 거기서 무슨 작업을 할지 묻지 않습니다.
  2. Google Cloud IAM 은 서비스 계정이 Google Cloud에서 무엇을 할 수 있는지 제어합니다. KCC가 바인딩 생성을 위해 Google Cloud를 호출하면 "KCC의 서비스 계정이 이 IAM 바인딩을 설정할 권한이 있는가?"라고 묻습니다. 가능하다면 허용합니다. Google Cloud는 어느 Kubernetes 사용자가 요청을 트리거했는지 알지 못하며, 그 사용자가 요청을 하도록 허가되어야 했는지도 확인하지 않습니다.

각 시스템이 요청의 절반씩만 검사하고, 전체를 검사하는 것은 없습니다

결과적으로 Kubernetes는 클러스터 내부에서 리소스가 생성되는 것만 보고, Google Cloud는 KCC의 서비스 계정이 변경을 수행하는 것만 봅니다. KCC는 접근 권한이 제한된 사용자의 요청을 받아, 그 사용자가 Google Cloud에서 갖지 못한 권한으로 실행할 수 있습니다.

이를 혼동된 대리인(confused deputy) 문제라고 합니다. KCC는 광범위한 권한을 가지고 더 적은 권한을 가진 사용자의 지시에 따라 행동하면서, 그들이 이를 활용할 수 있어야 하는지 확인하지 않습니다.

개발자에게서 클라우드 자격증명을 제거하는 설계 결정은 유용하고 의도적인 것입니다. 그러나 동시에 개발자의 Kubernetes 아이덴티티와 그들을 대신해 사용되는 Google Cloud 권한 사이의 연결 고리를 끊어버립니다. KCC가 행동할 때 Google Cloud는 KCC만 보고, 요청을 트리거한 사람은 보지 못합니다.

Google의 답변: "이건 기능입니다"

ConfigConfusion에 대한 Google의 답변은 KCC가 설계대로 동작하고 있다는 것이었습니다.

관리자가 KCC에 조직 수준 서비스 계정을 부여하기로 결정했고, 개발자가 KCC 관리 네임스페이스에서 IAMPolicyMember 리소스를 생성하도록 허용하기로 결정했습니다. Google의 관점에서 이는 설정상의 결정이며, KCC는 주어진 요청을 수행합니다.

이 설명은 기술적으로 정확하며, KCC는 설정된 대로 정확히 동작합니다.

문제는 문서가 이 두 가지 결정 사이의 관계를 명확하게 설명하지 않는다는 점입니다. 대부분의 관리자는 두 가지를 별개로 생각합니다. 이 팀이 어떤 Kubernetes 리소스 유형을 생성할 수 있는가, 그리고 KCC의 서비스 계정은 Google Cloud에서 무엇을 할 수 있는가? KCC에서 이 둘은 연결되어 있습니다. 팀에게 IAMPolicyMember 리소스를 생성할 권한을 주는 것은, 그 팀이 KCC의 Google Cloud 권한을 활용할 수 있는 수단을 주는 것이기도 합니다.

KCC에 필요한 정확한 권한을 파악하는 것이 어렵기 때문에 조직 수준 접근권한을 부여하는 것이 더 쉬울 때가 많습니다. 이것이 반드시 나쁜 관리를 의미하는 것은 아닙니다. 결과적인 권한 격차를 보이지 않게 만드는 설계의 자연스러운 결과입니다.

수정이 어려운 이유

가장 명백한 수정 방법은 요청을 실행하기 전에 리소스를 제출한 Kubernetes 사용자가 그에 상응하는 Google Cloud 권한을 갖고 있는지 확인하는 것입니다.

이 확인은 Kubernetes 사용자가 Google Cloud 아이덴티티를 갖고 있다는 것을 전제로 합니다. 그러나 KCC는 그들이 아이덴티티를 필요로 하지 않도록 설계되어 있습니다. 각 사용자에게 상응하는 아이덴티티를 부여하면 KCC가 제공하도록 설계된 모델이 무너지는 반면, 모든 리소스에 대해 요청자의 권한을 조회하면 모든 조정 사이클에 인가 검사와 추가적인 API 호출이 더해집니다.

따라서 Google이 권고하는 완화책은 각 요청을 인가하는 방식을 변경하는 것이 아니라, KCC를 통해 사용 가능한 권한을 줄이는 데 초점을 맞춥니다.

AWS와 Azure에도 동일한 위험이 있습니다

이 인가 문제는 KCC에만 국한된 것이 아닙니다. 한 아이덴티티의 지시를 받아 다른 아이덴티티를 통해 이를 수행하는 인프라 오퍼레이터는 동일한 격차를 만들 수 있습니다. 플랫폼에 따라 달라지는 것은 오퍼레이터가 보유한 권한의 크기와 그 권한을 얼마나 쉽게 제한할 수 있는지입니다.

  1. AWS Controllers for Kubernetes(ACK) 는 서비스별로 컨트롤러를 분리합니다. IAM, Amazon S3, Amazon EC2는 각각 해당 서비스로 범위가 제한된 IAM 역할을 가진 별도의 컨트롤러를 갖습니다. 사용자가 S3 컨트롤러의 요청 경로를 장악하더라도 S3 리소스에만 영향을 줄 수 있으며, 해당 역할에 그런 권한이 없으므로 IAM 변경은 불가합니다.
  2. Azure Service Operator v2 는 각 Kubernetes 네임스페이스가 별도의 관리 아이덴티티를 사용할 수 있도록 합니다. 이를 통해 관리자는 오퍼레이터 전체의 권한을 하나의 아이덴티티 뒤에 두는 대신, 네임스페이스별로 권한을 제한하는 실용적인 방법을 갖게 됩니다.

두 접근 방식 모두 근본적인 혼동된 대리인 위험을 제거하지는 못하지만, 악의적인 요청이 오퍼레이터에 도달하기 전에 권한을 제한함으로써 잠재적 피해를 줄입니다.

Config Connector를 안전하게 구성하는 방법

이 위험을 줄이려면 권한 격차의 양쪽을 모두 제한해야 합니다. Google Cloud에서 KCC의 서비스 계정이 할 수 있는 것과, KCC가 처리할 리소스를 제출할 수 있는 Kubernetes 사용자가 누구인지입니다.

아래 체크리스트는 양쪽을 모두 다룹니다.

  • KCC가 네임스페이스 모드를 사용하고, 각 네임스페이스마다 별도로 범위가 지정된 Google 서비스 계정을 사용하는가?
  • 프로젝트, 폴더, 조직 수준에서 KCC의 IAM 역할을 검토했는가?
  • 엄격히 필요하지 않은 한, roles/owner 및 roles/resourcemanager.organizationAdmin 같은 광범위한 역할이 제거되었는가?
  • IAMPolicyMember, IAMPolicy, IAMPartialPolicy 리소스 생성 권한이 승인된 플랫폼 또는 인프라 팀으로 제한되어 있는가?
  • 특히 승인된 GitOps 워크플로우 외부에서 KCC가 수행하는 폴더 및 조직 수준 IAM 변경을 모니터링하고 있는가?

취약한 구성은 조직 수준 IAM 권한을 가진 KCC 서비스 계정과 KCC 관리 네임스페이스에 대한 광범위한 쓰기 접근권한의 조합입니다.

두 조건 각각은 별도로 관리할 수 있지만, 함께 존재할 경우 Google Cloud 자격증명 없이도 악용할 수 있는 권한 상승 경로가 만들어집니다.

Varonis의 후원 및 작성.

출처
BleepingComputer · bleepingcomputer.com
원문 보기

분야별 뉴스

관심 분야의 보안 이슈를 모아 보세요.

TORUN SECURITY

투런이 제공하는 보안 솔루션

공격 표면 관리부터 엔드포인트·내부정보 보호까지, 기업 환경에 맞는 보안 솔루션을 투런이 함께 설계합니다.