AWS - EKS Post Exploitation
Reading time: 6 minutes
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
EKS
자세한 정보는 다음을 확인하세요
AWS Console에서 클러스터 열거
권한 **eks:AccessKubernetesApi**가 있으면 AWS EKS console을 통해 Kubernetes objects를 볼 수 있습니다 (Learn more).
AWS Kubernetes Cluster에 연결
- 쉬운 방법:
# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
- 그렇게 쉬운 방법은 아님:
만약 **aws eks get-token --name <cluster_name>**로 토큰을 얻을 수 있지만 cluster info (describeCluster)를 조회할 권한이 없다면, 자체 ~/.kube/config를 준비할 수 있다. 그러나 토큰을 가지고 있더라도 연결할 URL 엔드포인트(pod에서 JWT 토큰을 얻었다면 여기를 읽어보세요)와 클러스터 이름이 필요하다.
제 경우에는 CloudWatch 로그에서는 정보를 찾지 못했지만, LaunchTemaplates userData에서 찾았고 EC2 인스턴스의 userData에서도 찾았다. 이 정보는 userData에서 쉽게 확인할 수 있으며, 예를 들어 다음 예제에서(클러스터 이름은 cluster-name이었습니다):
API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com
/etc/eks/bootstrap.sh cluster-name --kubelet-extra-args '--node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=cluster-name,alpha.eksctl.io/nodegroup-name=prd-ondemand-us-west-2b,role=worker,eks.amazonaws.com/nodegroup-image=ami-002539dd2c532d0a5,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=prd-ondemand-us-west-2b,type=ondemand,eks.amazonaws.com/sourceLaunchTemplateId=lt-0f0f0ba62bef782e5 --max-pods=58' --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL --dns-cluster-ip $K8S_CLUSTER_DNS_IP --use-max-pods false
kube config
describe-cache-parametersapiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1USXlPREUyTWpjek1Wb1hEVE15TVRJeU5URTJNamN6TVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDlXCk9OS0ZqeXZoRUxDZGhMNnFwWkMwa1d0UURSRVF1UzVpRDcwK2pjbjFKWXZ4a3FsV1ZpbmtwOUt5N2x2ME5mUW8KYkNqREFLQWZmMEtlNlFUWVVvOC9jQXJ4K0RzWVlKV3dzcEZGbWlsY1lFWFZHMG5RV1VoMVQ3VWhOanc0MllMRQpkcVpzTGg4OTlzTXRLT1JtVE5sN1V6a05pTlUzSytueTZSRysvVzZmbFNYYnRiT2kwcXJSeFVpcDhMdWl4WGRVCnk4QTg3VjRjbllsMXo2MUt3NllIV3hhSm11eWI5enRtbCtBRHQ5RVhOUXhDMExrdWcxSDBqdTl1MDlkU09YYlkKMHJxY2lINjYvSTh0MjlPZ3JwNkY0dit5eUNJUjZFQURRaktHTFVEWUlVSkZ4WXA0Y1pGcVA1aVJteGJ5Nkh3UwpDSE52TWNJZFZRRUNQMlg5R2c4Q0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQVXFsekhWZmlDd0xqalhPRmJJUUc3L0VxZ1hNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBS1o4c0l4aXpsemx0aXRPcGcySgpYV0VUSThoeWxYNWx6cW1mV0dpZkdFVVduUDU3UEVtWW55eWJHbnZ5RlVDbnczTldMRTNrbEVMQVE4d0tLSG8rCnBZdXAzQlNYamdiWFovdWVJc2RhWlNucmVqNU1USlJ3SVFod250ZUtpU0J4MWFRVU01ZGdZc2c4SlpJY3I2WC8KRG5POGlHOGxmMXVxend1dUdHSHM2R1lNR0Mvd1V0czVvcm1GS291SmtSUWhBZElMVkNuaStYNCtmcHUzT21UNwprS3VmR0tyRVlKT09VL1c2YTB3OTRycU9iSS9Mem1GSWxJQnVNcXZWVDBwOGtlcTc1eklpdGNzaUJmYVVidng3Ci9sMGhvS1RqM0IrOGlwbktIWW4wNGZ1R2F2YVJRbEhWcldDVlZ4c3ZyYWpxOUdJNWJUUlJ6TnpTbzFlcTVZNisKRzVBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-west-2.eks.amazonaws.com
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
contexts:
- context:
cluster: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
user: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
current-context: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
kind: Config
preferences: {}
users:
- name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- --region
- us-west-2
- --profile
- <profile>
- eks
- get-token
- --cluster-name
- <cluster-name>
command: aws
env: null
interactiveMode: IfAvailable
provideClusterInfo: false
Kubernetes에서 AWS로
The creator of the EKS cluster is 항상 kubernetes 클러스터의 system:masters 그룹(=k8s admin)에 접근할 수 있습니다. 이 문서 작성 시점에는 클러스터를 누가 생성했는지 직접 확인할 방법이 없습니다 (CloudTrail을 확인할 수 있습니다). 그리고 그 권한을 제거하는 방법도 없습니다.
K8s에 대한 접근을 더 많은 AWS IAM 사용자나 역할에게 부여하는 방법은 configmap aws-auth 를 사용하는 것입니다.
warning
그러므로, config map **aws-auth**에 대한 write access 권한을 가진 누구든지 compromise the whole cluster할 수 있습니다.
For more information about how to grant extra privileges to IAM roles & users in the same or different account and how to abuse this to privesc check this page.
Check also this awesome post to learn how the authentication IAM -> Kubernetes work.
From Kubernetes to AWS
It's possible to allow an OpenID authentication for kubernetes service account to allow them to assume roles in AWS. Learn how this work in this page.
GET Api Server Endpoint from a JWT Token
Decoding the JWT token we get the cluster id & also the region. Knowing that the standard format for EKS url is
https://<cluster-id>.<two-random-chars><number>.<region>.eks.amazonaws.com
' two chars'와 'number'에 대한 기준을 설명하는 문서를 찾지 못했습니다. 하지만 제가 테스트해 본 결과 다음 값들이 반복되는 것을 확인했습니다:
- gr7
- yl4
어쨌든 3글자에 불과하므로 bruteforce할 수 있습니다. 아래 스크립트를 사용하여 목록을 생성하세요
from itertools import product
from string import ascii_lowercase
letter_combinations = product('abcdefghijklmnopqrstuvwxyz', repeat = 2)
number_combinations = product('0123456789', repeat = 1)
result = [
f'{''.join(comb[0])}{comb[1][0]}'
for comb in product(letter_combinations, number_combinations)
]
with open('out.txt', 'w') as f:
f.write('\n'.join(result))
그런 다음 wfuzz로
wfuzz -Z -z file,out.txt --hw 0 https://<cluster-id>.FUZZ.<region>.eks.amazonaws.com
warning
교체해야 할 것을 기억하세요 & .
CloudTrail 우회
공격자가 AWS에서 EKS에 대한 권한을 가진 자격증명을 획득한 경우, 공격자가 이전에 설명한 것처럼 자신의 **kubeconfig를 (update-kubeconfig**를 호출하지 않고) 구성하면, **get-token**은 AWS API와 상호작용하지 않기 때문에 Cloudtrail에 로그를 남기지 않습니다(로컬에서 토큰만 생성함).
따라서 공격자가 EKS 클러스터와 통신할 때, cloudtrail은 도용된 사용자가 접근한 것과 관련된 어떤 것도 로그로 남기지 않습니다.
참고로 EKS 클러스터에 로그가 활성화되어 있을 수 있으며 이 접근을 기록할 수 있습니다(기본적으로는 비활성화되어 있습니다).
EKS 랜섬?
기본적으로 클러스터를 생성한 **사용자 또는 역할(user or role)**은 클러스터에 대해 항상 관리자(admin) 권한을 갖습니다. 그리고 그것이 AWS가 Kubernetes 클러스터에 대해 갖는 유일한 "보안된" 접근 방식입니다.
따라서, 만약 공격자가 fargate를 사용해 클러스터를 침해하고 다른 모든 관리자들을 제거하고 d클러스터를 생성한 AWS 사용자/역할을 삭제하면, 공격자가 클러스터를 몸값으로 삼았을수 있다.
tip
클러스터가 EC2 VMs를 사용 중이었다면 Node에서 관리자 권한을 획득해 클러스터를 복구할 수 있을 가능성이 있습니다.
사실, 클러스터가 Fargate를 사용 중이라면 EC2 노드를 만들거나 모든 것을 EC2로 옮겨 노드의 토큰에 접근해 복구할 수 있습니다.
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks Cloud