쿠버네티스 API 서버 우회 위험

쿠버네티스 API 서버 우회 위험 (Kubernetes API Server Bypass Risks)

쿠버네티스 API 서버는 클러스터와 상호 작용하는 외부 당사자(사용자와 서비스)에게 클러스터의 주요 진입점이에요.

이 역할의 일부로 API 서버는 감사 로깅과 admission 컨트롤러 같은 몇 가지 핵심 내장 보안 제어를 가져요. 하지만 이런 제어를 우회해 클러스터의 구성이나 콘텐츠를 수정하는 방법이 존재해요.

이 페이지는 쿠버네티스 API 서버에 내장된 보안 제어가 우회될 수 있는 방법을 설명해, 클러스터 운영자와 보안 설계자가 이런 우회를 적절히 제한할 수 있도록 해요.

출처: 문서

본문

정적 파드 (Static Pods)

각 노드의 kubelet은 이름 붙은 디렉토리에 저장되거나 특정 URL에서 가져온 매니페스트를 클러스터의 정적 파드로 로드하고 직접 관리해요. API 서버는 이 정적 파드를 관리하지 않아요. 이 위치에 쓰기 접근을 가진 공격자는 그 소스에서 로드된 정적 파드의 구성을 수정하거나 새 정적 파드를 도입할 수 있어요.

정적 파드는 쿠버네티스 API의 다른 객체에 접근하는 것이 제한돼요. 예를 들어 정적 파드가 클러스터의 Secret을 마운트하도록 구성할 수 없어요. 하지만 이 파드들은 기저 노드의 hostPath 마운트 사용 같은 다른 보안에 민감한 조치를 취할 수 있어요.

기본적으로 kubelet은 mirror pod을 만들어 정적 파드가 쿠버네티스 API에 보이게 해요. 하지만 공격자가 파드를 만들 때 잘못된 네임스페이스 이름을 사용하면 그 파드는 쿠버네티스 API에 보이지 않고, 영향을 받은 호스트에 접근할 수 있는 도구로만 발견될 수 있어요.

정적 파드가 admission 제어에 실패하면 kubelet은 그 파드를 API 서버에 등록하지 않아요. 하지만 파드는 여전히 노드에서 실행돼요. 자세한 내용은 kubeadm issue #1541을 참고해요.

완화 (Mitigations)

  • 노드에서 필요할 때만 kubelet 정적 파드 매니페스트 기능을 활성화해요.
  • 노드가 정적 파드 기능을 사용한다면, 정적 파드 매니페스트 디렉토리나 URL에 대한 파일 시스템 접근을 접근이 필요한 사용자로 제한해요.
  • 공격자가 정적 파드 경로나 URL을 설정하지 못하도록 kubelet 구성 매개변수와 파일에 대한 접근을 제한해요.
  • 정적 파드 매니페스트와 kubelet 구성 파일을 호스팅하는 디렉토리나 웹 저장 위치에 대한 모든 접근을 정기적으로 감사하고 중앙에서 보고해요.

kubelet API

kubelet은 일반적으로 클러스터 워커 노드의 TCP 포트 10250에 노출되는 HTTP API를 제공해요. 사용 중인 쿠버네티스 배포에 따라 이 API가 제어 플레인 노드에도 노출될 수 있어요. API에 직접 접근하면 노드에서 실행 중인 파드에 대한 정보, 그 파드의 로그 노출, 그리고 노드에서 실행되는 모든 컨테이너에서 명령 실행이 가능해져요.

이 엔드포인트 중 일부는 HTTP GET 요청을 통해 Websocket 프로토콜을 지원하며, 이는 get 동사로 인가돼요. 이는 nodes/proxy 에 대한 get 권한이 읽기 전용 권한이 아니며, 노드에서 실행되는 모든 컨테이너에서 명령을 실행하는 데 사용될 수 있는 엔드포인트에 대한 접근을 인가한다는 뜻이에요.

쿠버네티스 클러스터 사용자가 Node 객체 하위 리소스에 대해 RBAC 접근을 가지면, 그 접근은 kubelet API와 상호 작용하기 위한 인가로 작동해요. 정확한 접근은 kubelet authorization에 자세히 설명된 대로 어떤 하위 리소스 접근이 부여됐는지에 따라 달라져요.

kubelet API에 대한 직접 접근은 admission 제어의 적용을 받지 않으며 쿠버네티스 감사 로깅으로 기록되지 않아요. 이 API에 직접 접근할 수 있는 공격자는 특정 조치를 감지하거나 방지하는 제어를 우회할 수 있을지도 몰라요.

kubelet API는 다양한 방식으로 요청을 인증하도록 구성될 수 있어요. 기본적으로 kubelet 구성은 익명 접근을 허용해요. 대부분의 쿠버네티스 제공자는 기본값을 webhook와 인증서 인증을 사용하도록 변경해요. 이렇게 하면 제어 플레인이 호출자가 nodes API 리소스나 하위 리소스에 접근할 권한이 있는지 확인할 수 있어요. 기본 익명 접근은 제어 플레인으로 이 단언을 하지 않아요.

완화 (Mitigations)

  • RBAC 같은 메커니즘을 사용해 nodes API 객체의 하위 리소스에 대한 접근을 제한해요. 모니터링 서비스처럼 필요할 때만 이 접근을 부여해요.
  • get 동사만으로도 nodes/proxy catch-all 권한 부여를 피해요. 대신 세분화된 권한을 부여해요.
  • kubelet 포트에 대한 접근을 제한해요. 지정되고 신뢰된 IP 주소 범위만 포트에 접근하도록 허용해요.
  • kubelet 인증이 webhook 또는 인증서 모드로 설정되도록 보장해요.
  • 클러스터에서 인증되지 않은 "read-only" Kubelet 포트가 활성화되지 않도록 보장해요.

etcd API

쿠버네티스 클러스터는 etcd를 데이터 저장소로 사용해요. etcd 서비스는 TCP 포트 2379에서 수신해요. 접근이 필요한 유일한 클라이언트는 쿠버네티스 API 서버와 사용하는 백업 도구예요. 이 API에 직접 접근하면 클러스터에 보관된 모든 데이터의 노출이나 수정이 가능해져요.

etc 세대 API에 대한 접근은 일반적으로 클라이언트 인증서 인증으로 관리돼요. etcd가 신뢰하는 인증 기관이 발급한 모든 인증서는 etcd 내부에 저장된 데이터에 대한 전체 접근을 허용해요.

etcd에 대한 직접 접근은 쿠버네티스 admission 제어의 적용을 받지 않으며 쿠버네티스 감사 로깅으로 기록되지 않아요. API 서버의 etcd 클라이언트 인증서 개인 키에 대한 읽기 접근을 가진(또는 새 신뢰할 수 있는 클라이언트 인증서를 만들 수 있는) 공격자는 클러스터의 Secret에 접근하거나 접근 규칙을 수정해 클러스터 관리자 권한을 얻을 수 있어요. 쿠버네티스 RBAC 권한을 승격시키지 않더라도, etcd를 수정할 수 있는 공격자는 클러스터 안에서 어떤 API 객체든 검색하거나 새 워크로드를 만들 수 있어요.

많은 쿠버네티스 제공자는 상호 TLS(클라이언트와 서버가 서로의 인증서를 확인해 인증)를 사용하도록 etcd를 구성해요. etcd API에 대한 인가의 널리 받아들여진 구현은 없지만 기능은 존재해요. 인가 모델이 없으므로 etcd에 대한 클라이언트 접근이 있는 모든 인증서로 etcd에 전체 접근을 얻을 수 있어요. 일반적으로 헬스 체크에만 사용되는 etcd 클라이언트 인증서도 전체 읽기·쓰기 접근을 부여할 수 있어요.

완화 (Mitigations)

  • etcd가 신뢰하는 인증 기관이 그 서비스에 대한 인증 목적으로만 사용되도록 보장해요.
  • etcd 서버 인증서의 개인 키와 API 서버의 클라이언트 인증서·키에 대한 접근을 제어해요.
  • 네트워크 수준에서 etcd 포트에 대한 접근을 제한해, 지정되고 신뢰된 IP 주소 범위에서만 접근을 허용하는 것을 고려해요.

컨테이너 런타임 소켓 (Container runtime socket)

쿠버네티스 클러스터의 각 노드에서 컨테이너와 상호 작용하는 접근은 컨테이너 런타임(두 개 이상 구성했다면 런타임들)이 제어해요. 일반적으로 컨테이너 런타임은 kubelet이 접근할 수 있는 Unix 소켓을 노출해요. 이 소켓에 접근할 수 있는 공격자는 새 컨테이너를 시작하거나 실행 중인 컨테이너와 상호 작용할 수 있어요.

클러스터 수준에서 이 접근의 영향은 손상된 노드에서 실행되는 컨테이너가 공격자가 다른 워커 노드나 제어 플레인 컴포넌트로 권한을 승격하는 데 사용할 수 있는 Secret이나 다른 기밀 데이터에 접근할 수 있는지에 따라 달라져요.

완화 (Mitigations)

  • 컨테이너 런타임 소켓에 대한 파일 시스템 접근을 엄격히 제어하도록 보장해요. 가능하면 root 사용자로 이 접근을 제한해요.
  • Linux 커널 네임스페이스 같은 메커니즘을 사용해 kubelet을 노드에서 실행되는 다른 컴포넌트와 격리해요.
  • 컨테이너 런타임 소켓을 포함하는 hostPath 마운트를 직접 또는 상위 디렉토리를 마운트해 제한하거나 금지하도록 보장해요. 또한 공격자가 디렉토리 제한을 우회하는 위험을 완화하기 위해 hostPath 마운트는 읽기 전용으로 설정해야 해요.
  • 사용자의 노드 접근을 제한하고, 특히 노드에 대한 슈퍼유저 접근을 제한해요.

더 알아보기 (Learn more)