# You could update instead of creategcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
K8s에서 GCP 권한으로 가짜 GCP 서비스 계정을 생성합니다:
# Create SA called "gsa2ksa"gcloudiamservice-accountscreategsa2ksa--project=<project-id># Give "roles/iam.securityReviewer" role to the SAgcloudprojectsadd-iam-policy-binding<project-id> \--member "serviceAccount:gsa2ksa@<project-id>.iam.gserviceaccount.com" \--role "roles/iam.securityReviewer"
클러스터에 연결하고 사용할 서비스 계정을 생성합니다.
# Get k8s credsgcloudcontainerclustersget-credentials<cluster_name>--region=us-central1# Generate our testing namespacekubectlcreatenamespacetesting# Create the KSAkubectlcreateserviceaccountksa2gcp-ntesting
GSA를 KSA와 바인딩하기
# Allow the KSA to access the GSA in GCP IAMgcloudiamservice-accountsadd-iam-policy-bindinggsa2ksa@<project-id.iam.gserviceaccount.com \--role roles/iam.workloadIdentityUser \--member "serviceAccount:<project-id>.svc.id.goog[<namespace>/ksa2gcp]"# Indicate to K8s that the SA is able to impersonate the GSAkubectlannotateserviceaccountksa2gcp \--namespace testing \iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
KSA로 pod를 실행하고 GSA에 대한 접근을 확인합니다:
# If using Autopilot remove the nodeSelector stuff!echo"apiVersion: v1kind: Podmetadata:name: workload-identity-testnamespace: <namespace>spec:containers:- image: google/cloud-sdk:slimname: workload-identity-testcommand: ['sleep','infinity']serviceAccountName: ksa2gcpnodeSelector:iam.gke.io/gke-metadata-server-enabled: 'true'"|kubectlapply-f-# Get inside the podkubectlexec-itworkload-identity-test \--namespace testing \-- /bin/bash# Check you can access the GSA from insie the pod withcurl-H"Metadata-Flavor: Google"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/emailgcloudauthlist
K8s 내부의 공격자로서 iam.gke.io/gcp-service-account 주석이 있는 SAs를 검색해야 합니다. 이는 SA가 GCP의 무언가에 접근할 수 있음을 나타냅니다. 또 다른 옵션은 클러스터 내의 각 KSA를 남용해보고 접근 권한이 있는지 확인하는 것입니다.
GCP에서 항상 바인딩을 나열하고 Kubernetes 내 SAs에 어떤 접근 권한을 부여하고 있는지 아는 것이 흥미롭습니다.
이것은 주석을 찾기 위해 모든 포드 정의를 쉽게 반복하는 스크립트입니다:
for ns in`kubectlgetnamespaces-ocustom-columns=NAME:.metadata.name|grep-vNAME`; dofor pod in`kubectlgetpods-n "$ns" -ocustom-columns=NAME:.metadata.name|grep-vNAME`; doecho"Pod: $ns/$pod"kubectlgetpod"$pod"-n"$ns"-oyaml|grep"gcp-service-account"echo""echo""donedone|grep-B1"gcp-service-account"
AWS
Kiam & Kube2IAM (IAM 역할을 위한 Pods)
Pods에 IAM 역할을 부여하는 (구식) 방법은 Kiam 또는 Kube2IAM서버를 사용하는 것입니다. 기본적으로 클러스터에서 특권 IAM 역할의 데몬셋을 실행해야 합니다. 이 데몬셋이 필요한 Pods에 IAM 역할에 대한 접근을 제공합니다.
먼저 네임스페이스 내에서 접근할 수 있는 역할을 구성해야 하며, 이는 네임스페이스 객체 내의 주석을 통해 수행합니다:
공격자로서, 만약 당신이 이 주석을 파드나 네임스페이스에서 발견하거나 kiam/kube2iam 서버가 실행 중인 것을 발견한다면 (아마도 kube-system에서) 당신은 파드에서 이미 사용되고 있는 모든 role을 가장할 수 있으며, 더 많은 것을 할 수 있습니다 (AWS 계정에 접근할 수 있다면 역할을 나열하십시오).
IAM 역할로 파드 생성
지정해야 할 IAM 역할은 kiam/kube2iam 역할과 동일한 AWS 계정에 있어야 하며, 그 역할은 접근할 수 있어야 합니다.
IAM 역할과 SA 간의 신뢰 관계를 생성합니다 (또는 역할에 대한 액세스를 모든 SA에 부여하는 네임스페이스). 신뢰 관계는 주로 OIDC 공급자 이름, 네임스페이스 이름 및 SA 이름을 확인합니다.
마지막으로, 역할의 ARN을 나타내는 주석이 있는 SA를 생성하면, 해당 SA로 실행되는 포드는 역할의 토큰에 접근할 수 있습니다. 토큰은 **파일에 기록되며 경로는 **AWS_WEB_IDENTITY_TOKEN_FILE에 지정됩니다 (기본값: /var/run/secrets/eks.amazonaws.com/serviceaccount/token)
# Create a service account with a rolecat>my-service-account.yaml<<EOFapiVersion: v1kind: ServiceAccountmetadata:name: my-service-accountnamespace: defaultannotations:eks.amazonaws.com/role-arn: arn:aws:iam::318142138553:role/EKSOIDCTestingEOFkubectlapply-fmy-service-account.yaml# Add a role to an existent service accountkubectl annotate serviceaccount -n $namespace $service_account eks.amazonaws.com/role-arn=arn:aws:iam::$account_id:role/my-role
To get aws using the token from /var/run/secrets/eks.amazonaws.com/serviceaccount/token run:
공격자로서 K8s 클러스터를 열거할 수 있다면, AWS로 상승하기 위해 해당 주석이 있는 서비스 계정을 확인하십시오. 그렇게 하려면, IAM 특권 서비스 계정 중 하나를 사용하여 pod를 exec/create하고 토큰을 훔치면 됩니다.
또한, pod 내부에 있다면 AWS_ROLE_ARN 및 AWS_WEB_IDENTITY_TOKEN과 같은 환경 변수를 확인하십시오.
때때로 역할의 신뢰 정책이 잘못 구성되어 예상되는 서비스 계정에 AssumeRole 액세스를 부여하는 대신 모든 서비스 계정에 부여할 수 있습니다. 따라서 제어된 서비스 계정에 주석을 작성할 수 있다면, 해당 역할에 접근할 수 있습니다.
자세한 정보는 다음 페이지를 확인하십시오:
클러스터에서 IAM 역할이 있는 SAs의 Pods 찾기
이 스크립트는 모든 pod와 sa 정의를 쉽게 반복하여 해당 주석을 찾는 것입니다:
for ns in`kubectlgetnamespaces-ocustom-columns=NAME:.metadata.name|grep-vNAME`; dofor pod in`kubectlgetpods-n "$ns" -ocustom-columns=NAME:.metadata.name|grep-vNAME`; doecho"Pod: $ns/$pod"kubectlgetpod"$pod"-n"$ns"-oyaml|grep"amazonaws.com"echo""echo""donefor sa in`kubectlgetserviceaccounts-n "$ns" -ocustom-columns=NAME:.metadata.name|grep-vNAME`; doecho"SA: $ns/$sa"kubectlgetserviceaccount"$sa"-n"$ns"-oyaml|grep"amazonaws.com"echo""echo""donedone|grep-B1"amazonaws.com"
Node IAM Role
이전 섹션은 pods로 IAM Roles를 훔치는 방법에 대한 것이었지만, K8s 클러스터의 Node는 클라우드 내의 인스턴스가 될 것임을 주목하세요. 이는 Node가 훔칠 수 있는 새로운 IAM 역할을 가질 가능성이 높다는 것을 의미합니다 (일반적으로 K8s 클러스터의 모든 노드는 동일한 IAM 역할을 가지므로 각 노드를 확인하려고 시도하는 것이 그다지 가치가 없을 수 있습니다).
그러나 노드에서 메타데이터 엔드포인트에 접근하기 위한 중요한 요구 사항이 있습니다. 노드에 있어야 하거나 (ssh 세션?) 최소한 동일한 네트워크에 있어야 합니다: