블로그

컨테이너 보안 기본 사항: 오케스트레이션

  조던 제보르

  로리 맥비티

2019년 7월 24일 게시

이 시리즈를 처음 접하는 분이라면 처음부터 시작해 보세요. 
컨테이너 보안 기본 사항: 소개
컨테이너 보안 기본 사항: 관로

Tripwire의 2019년 컨테이너 보안 현황 에 따르면, 약 3분의 1(32%)의 조직이 현재 운영 환경에서 100개가 넘는 컨테이너를 운영하고 있습니다. 더 적은 비율(13%)이 500개 이상을 운영하고 있습니다. 그리고 진정으로 적극적으로 채택하는 사람의 6%는 현재 1,000개 이상을 관리하고 있습니다. 오케스트레이션 시스템의 도움 없이 대규모 컨테이너를 운영하는 조직은 거의 없습니다.

컨테이너 보안의 오케스트레이션 계층은 컨테이너의 일상적인 운영을 담당하는 환경에 초점을 맞춥니다. 오늘날 사용 가능한 데이터에 따르면 컨테이너를 사용하는 경우 거의 확실히 오케스트레이터로 Kubernetes를 활용하고 있는 것입니다.

다른 오케스트레이터도 있지만 대부분은 Kubernetes에서 파생된 구성 요소와 개념을 활용하고 있다는 점에 유의하는 것이 중요합니다. 따라서 우리는 Kubernetes와 그 구성 요소의 보안에 집중할 것입니다.

쿠버네티스 환경

Kubernetes를 구성하는 여러 가지 움직이는 부분이 있습니다. 이로 인해 보안이 더 어려워지는 것은 관련된 구성 요소의 수 때문일 뿐만 아니라 해당 구성 요소가 상호 작용하는 방식 때문입니다. 일부는 API를 통해 통신합니다. 다른 일부는 호스트 파일 시스템을 통해 통신합니다. 이러한 모든 요소는 반드시 해결해야 하는 오케스트레이션 환경으로의 잠재적 진입점입니다. 

기본 쿠버네티스 환경

기본 쿠버네티스 환경

주의가 필요한 핵심 구성 요소에 대한 간략한 개요:

  • API 서버 및 Kubelet
  • 포드
  • 기타

그러니까 커피 한 잔을 마시라는 뜻이에요. 이걸 다 마치려면 좀 더 시간이 걸릴 거예요.

1. 인증은 선택 사항이 아닙니다

눈치 빠른 독자라면 이것이 익숙하게 들릴 것입니다. 보안 규칙 2라고도 하는 것을 들어보셨을 것입니다. 문을 잠그세요. 이는 종종 무시되기 때문에 우리가 계속해서 반복하게 될 일반적인 주제입니다. 강력한 인증이 필수입니다. 우리는 컨테이너와 관련된 보안 관행이 부족해 보안 사고가 계속 늘어나는 모습을 지켜보고 있습니다. 그리고 일반적인 원인 중 하나는 인증을 사용하지 못하는 것인데, 이는 일반적으로 퍼블릭 클라우드에 배포되는 경우입니다.

강력한 자격 증명을 요구하고 자주 교체하십시오. API 서버에 액세스(보안되지 않은 콘솔을 통해)하면 전체 오케스트레이션 환경을 제어할 수 있으므로 "게임 오버" 상황으로 이어질 수 있습니다. 즉, Pod 배포, 구성 변경, 컨테이너 중지/시작을 의미합니다. 쿠버네티스 환경에서 API 서버는 악의적인 행위자의 손에 들어가지 않도록 보호해야 하는 "모든 것을 제어하는 하나의 API"입니다.

API 서버와 Kubelet을 보호하는 방법

이러한 권장 사항은 현재의 Kubernetes 권한 부여 모델을 기반으로 한다는 점에 유의하는 것이 중요합니다. 항상 사용하는 버전의 최신 설명서를 참조하세요.

  • 모든 곳에서 mTLS를 활성화하세요
    - 서비스당 CA 전용 – k8s, etcd, 애플리케이션
    - 인증서 회전 및 디스크의 개인 키 권한에 주의하세요
  • 보안 주소에만 바인딩하세요
    - API 구성 "insecure-bind-address" 및 "insecure-port"에 주의하세요.
    - 이것을 _모든_ 서비스(SSH, Vault 등)에 적용합니다.
  • "익명 인증" 비활성화
    - "익명 인증"이 좋은 생각인 것 같나요?
    - 1.5부터 기본적으로 비활성화되었으며 "--anonymous-auth=True"로 수동으로 활성화되었습니다.
  • 권한 부여 활성화
    - "--authorization-mode=AlwaysAllow"를 사용하지 마세요.
    - API 서버에는 "--authorization-mode=RBAC,Node"가 있어야 합니다.
    - Kubelet에는 "--authorization-mode=Webhook"이 있어야 합니다.
    - Kubelet이 자체 노드의 리소스에만 액세스하도록 제한합니다 .

이러한 권장 사항은 현재 Kubernetes 권한 부여 모델을 기반으로 한다는 점에 유의하는 것이 중요합니다. 항상 사용하는 버전의 최신 설명서를 참조하세요. 

2. 포드 및 권한 

포드는 컨테이너의 집합입니다. 이들은 가장 작은 쿠버네티스 구성 요소이며, 컨테이너 네트워크 인터페이스(CNI) 플러그인에 따라 달라지며, 모든 포드는 기본적으로 서로 연결할 수 있습니다. 이 기본 동작에 대한 제한을 구현하기 위해 "네트워크 정책"을 사용할 수 있는 CNI 플러그인이 있습니다. 이 점은 Pod가 서로 다른 Kubernetes 노드(물리적 서버와 유사)에 예약될 수 있기 때문에 중요합니다. 포드는 일반적으로 비밀을 마운트하는데, 비밀에는 개인 키, 인증 토큰 및 기타 민감한 정보가 포함될 수 있습니다. 그래서 이것을 '비밀'이라고 부르는 거예요.

즉, 포드와 보안에 대한 우려가 몇 가지 있다는 뜻입니다. F5에서는 위협 모델링을 시작할 때 항상 손상된 포드가 있다고 가정합니다. 그 이유는 애플리케이션 워크로드가 배포되는 곳이 포드이기 때문입니다. 애플리케이션 워크로드는 신뢰할 수 없는 액세스에 노출될 가능성이 가장 높으므로, 침해가 발생할 가능성이 가장 높습니다. 이러한 가정은 잠재적 위협을 완화하는 방법을 계획하기 위해 물어야 할 네 가지 기본 질문을 제기합니다. 

  1. 공격자는 다른 포드에 접근 권한을 부여했을 때 무엇을 볼 수 있고 무엇을 할 수 있을까?
  2. 공격자가 클러스터의 다른 서비스에 액세스할 수 있습니까?
  3. 어떤 비밀이 자동으로 마운트되나요?
  4. Pod 서비스 계정에 어떤 권한이 부여되었나요?

이러한 질문에 대한 답변은 공격자가 클러스터 내의 포드에 액세스하는 경우 악용될 수 있는 위험을 보여줍니다. 포드 손상 위협을 완화하려면 구성 옵션, 권한 제어, 시스템 수준 제한을 포함한 다각적인 접근 방식이 필요합니다. 여러 개의 Pod가 동일한 (물리적 또는 가상) 노드에 배포될 수 있으며, 따라서 운영 체제 액세스(일반적으로 Linux OS)를 공유할 수 있습니다.

Pod 위협을 완화하는 방법
쿠버네티스에는 Pod의 민감한 측면을 제어하는 Pod 보안 정책 리소스가 포함되어 있습니다. 이를 통해 운영자는 포드가 시스템에 진입하기 위해 작동해야 하는 조건을 정의할 수 있으며 포드 보안 컨텍스트에 대한 기준을 적용합니다. 절대로 기본값이 안전하다고 가정하지 마십시오. 안전한 기준선을 구현하고 기대치를 검증하여 포드 위협으로부터 보호합니다.

Pod 보안 정책에 대한 구체적인 옵션은 다음 사항을 다루어야 합니다.

  • 특권 컨테이너를 피하세요
    • kube-api 및/또는 kubelet에서 "—allow-privileged" 설정을 찾으세요.
    • Pod 사양에서 "privileged: true"를 찾으세요.
    • "--allow-privileged=false"로 보안 위험 감소
  • Docker의 기본 컨테이너 사용자는 root입니다.
    • 루트로 작업 부하를 실행하지 마십시오.
    • Pod 보안 정책은 "runAsUser", "runAsGroup" 및 "runAsNonRoot: true"를 사용할 수 있습니다.
    • Dockerfile에서 유사한 옵션을 정의할 수 있습니다.
  • 컨테이너 내에서 권한 상승을 허용하지 않음
    • “allowPrivilegeEscalation: 거짓”
  • SELinux / AppArmor 사용
    • SELinux는 다중 범주 보안을 사용하여 컨테이너를 서로 제한합니다.
    • 활성화된 상태로 두고 거부를 처리합니다.
    • 허용 모드를 비활성화하거나 변경하면 보안이 심각하게 저하됩니다.
  • Sym 링크/진입점 공격 방지
    • 공격자는 진입점 바이너리를 덮어쓰거나 잘못된 심볼릭 링크를 생성할 수 있습니다.
    • “readOnlyRootFilesystem: true”를 설정하여 이를 방지하세요.
  • 호스트* 구성 옵션을 사용하지 마세요
    • 호스트 리소스에 액세스할 수 있는 공격자는 호스트 및/또는 인접 컨테이너에 대한 손상을 더욱 심화시킬 가능성이 더 높습니다.
    • hostPID, hostIPC, hostNetwork, hostPorts와 같은 옵션은 피하세요.
  • readOnly hostPath 마운트
    • 호스트에 대한 읽기/쓰기를 구성해야 하는 경우 배포에 주의하고 이를 기본 작업으로 삼지 마십시오.
    • 공격을 방지하려면 모든 허용된 호스트 경로에 "readOnly"를 사용하세요.
  • Seccomp 프로필
    • 허용되는 시스템 호출을 제한하여 위협 표면을 줄입니다.
    • Docker 기본값은 일부를 줄이겠지만 그것은 일반적인 프로필입니다
    • 애플리케이션별 프로필은 가장 큰 보안 이점을 제공합니다.

3. 기타

Etcd는 구성과 비밀을 저장하는 곳입니다. 이러한 침해로 인해 민감한 데이터가 추출되거나 악성 데이터가 삽입될 수 있습니다. 둘 다 좋지 않습니다. etcd에 대한 위협을 완화하려면 액세스를 제어해야 합니다. 이 문제는 mTLS를 적용 하여 해결하는 것이 가장 좋습니다. 비밀은 Kubernetes에 의해 base64로 인코딩되어 etcd 에 저장됩니다. 민감한 비밀을 저장할 때 더 강력한 옵션을 위해 알파 기능인 "암호화 공급자"를 사용하거나 HashiCorp Vault를 사용하는 것을 고려하세요.

이 시리즈의 다음 블로그를 읽어보세요. 
컨테이너 보안 기본 사항: 작업량