一、前言

当前互联网向虚拟化发展,容器是重要的组成部分,具有占用资源少部署快的强大优点。比如常见的docker。当容器规模大了以后,就需要对这些容器集群进行编排维护,所以就有了k8s技术。

k8s全称kubernetes,是一个由google开源的k8s认证,用于自动部署,扩展和管理容器化应用程序的开源系统。通过k8s可跨多台主机进行容器编排、快速按需扩展容器化应用及其资源、对应用实施状况检查、服务发现和负载均衡等。

随着越来越多的企业将业务搬上云,攻防中遇见类似的虚拟化集群场景会越来越多。这里简单介绍下k8s的结构和攻击利用的方式,不算太深,希望给大家遇到的相同场景的时候提供个思路。

二、k8s组件结构简介

我们用一幅图来介绍相关组件。

mesos k8s_k8s认证_阿里云k8s和自建k8s区别

如图所示,k8s集群由主控节点(Master node,以下简称master)和工作节点(Worker Node,以下简称node)组成:

master节点负责资源调度,调度应用,维护状态和应用扩容等。

node节点上跑着应用服务,每个Node节点有一个kubelet,负责node与master之间的通信。

2.1 Master node组件

1.APIserver

集群统一入口,以restful方式,交给etcd存储。用户端一般通过kubectl命令行工具与kube-apiserver进行交互。

2.Controller-manager

处理集群中常规后台任务,通常一个资源对应一个控制器。

3.Scheduler

节点调度,选择node节点应用部署,负责决定将Pod放在哪个Node上。会对各个节点的负载、性能、数据考虑最优的node。

4.Etcd

存储系统,用于保存集群中相关的数据。

2.2 Worker node组件

5.Kubelet

Master派到node节点的agent,管理本机容器的各种操作。

6.Kube-proxy

提供网络代理,用来实现负载均衡等操作。

7.Pod

是k8s中的最小部署单元,一组容器的集合,一个pod中的容器是共享网络的。主要是基于docker技术来搭建的。

2.3 工作流程

用户端命令下发通常流程如下:

(1)客户端根据用户需求,调用kube-apiserver相应api;

(2)kube-apiserver根据命令类型,联动master节点内的kube-controller-manager和kube-scheduler等组件,通过kubelet进行下发新建容器配置或下发执行命令等给到对应node节点;

(3)node节点与容器进行交互完成下发的命令并返回结果;

(4)master节点最终根据任务类型将结果持久化存储在etcd中。

三、k8s的安全机制

访问k8s集群的时候,需要经过三个安全步骤完成具体操作。过程中都要经过apiserver,apiserver做统一协调。

第一步 认证,判断用户是否为能够访问集群的合法用户。

第二步 鉴权,通过鉴权策略决定一个API调用是否合法。

第三步 准入控制,就算通过了上面两步,客户端的调用请求还需要通过准入控制的层层考验,才能获得成功的响应。大致意思就是到了这步还有一个类似acl的列表,如果列表有请求内容,就通过,否则不通。它以插件的形式运行在API Server进程中,会在鉴权阶段之后,对象被持久化etcd之前,拦截API Server的请求,对请求的资源对象执行自定义(校验、修改、拒绝等)操作。

这里说下认证和鉴权。

3.1 认证阶段

认证策略大概有4种:

序号

认证方式

认证凭据

1

匿名认证

Anonymous requests

2

白名单认证

BasicAuth认证

3

Token认证

Webhooks、ServiceAccount Tokens、OpenID Connect Tokens等

4

X509证书认证

clientCA认证,TLS bootstrapping等

匿名认证一般默认是关闭的。

白名单认证一般是服务启动时加载的basic用户配置文件,并且通常没有更多设置的话basic认证仅仅只能访问但是没有操作权限。

token认证更涉及到对集群和pod的操作,这是我们比较关注的。

X509证书认证是kubernetes组件间内部默认使用的认证方式,同时也是kubectl客户端对应的kube-config中经常使用到的访问凭证,是一种比较安全的认证方式。

3.2 鉴权阶段

当API Server内部通过用户认证后,就会执行用户鉴权流程,即通过鉴权策略决定一个API调用是否合法,API Server目前支持以下鉴权策略:

序号

鉴权方式

描述

1

Always

当集群不需要鉴权时选择AlwaysAllow

2

ABAC

基于属性的访问控制

3

RBAC

基于角色的访问控制

k8s认证_阿里云k8s和自建k8s区别_mesos k8s

4

Node

一种对kubelet进行授权的特殊模式

5

Webhook

通过调用外部REST服务对用户鉴权

Always策略光看描述就知道,生产环境中必定不会存在。

ABAC虽然功能强大,但是难以理解且配置复杂已经被RBAC替代。

RBAC是目前k8s中最主要的鉴权方式。

而Node鉴权策略主要是用于对kubelet发出的请求进行访问控制,限制每个Node只访问它自身运行的Pod及相关Service、Endpoints等信息。

当RBAC无法满足某些特定需求时候,可自行编写鉴权逻辑并通过Webhook方式注册为kubernetes的授权服务,以实现更加复杂的授权规则。

3.3 RBAC、角色、账号、命名空间

这里要着重讲一下RBAC,基于角色的访问控制(Role-Based Access Control)在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。

阿里云k8s和自建k8s区别_mesos k8s_k8s认证

在k8s中,只有对角色的权限控制,访问主体都必须通过角色绑定,绑定成k8s集群中对应的角色,然后根据绑定的角色去访问资源。而每种角色又只能访问它所对应的命名空间中的资源。

k8s支持多个虚拟集群,它们底层依赖于同一个物理集群。这些虚拟集群被称为命名空间(namespace)。

每个k8s资源只能在一个命名空间中。命名空间是在多个用户之间划分集群资源的一种方法。

这些名词初看起来比较头疼,我们先看下默认的角色,命名空间有哪些。

kubectl get ns 查看命名空间。

k8s认证_阿里云k8s和自建k8s区别_mesos k8s

系统默认4个命名空间,分别是:

default–没有指明使用其它名字空间的对象所使用的默认名字空间

kube-system– Kubernetes 系统创建对象所使用的名字空间

kube-public–此命名空间下的资源可被所有人访问(包括未授权用户)

kube-node-lease–集群之间的心跳维护

我们关注的主要是default和kube-system。

RBAC中一直强调角色,这里角色也分为两种,一种是普通角色role,一种是集群角色clusterrole。

普通角色role用于平常分配给运行的容器,而集群角色更多承担管理工作。

查看普通角色,没有特别指明的话查看都是在default空间中,这里因为没有设置,所以显示找不到。

指定kube-system空间,可以看到很多系统自带的角色。

阿里云k8s和自建k8s区别_k8s认证_mesos k8s

再来看集群角色。集群角色在default和kube-system中都是一样的。

阿里云k8s和自建k8s区别_k8s认证_mesos k8s

集群中有个最高权限角色cluster-admin,它的拥有集群所有资源的所有权限。因此如果访问主体绑定到该角色的话,就会引发很大的安全问题,后续说到的未授权访问就是基于此种情形。

k8s认证_mesos k8s_阿里云k8s和自建k8s区别

普通的admin权限也比较大,但是比起cluster-admin还是差了太多。

如何要绑定账号的话,比如在集群范围将cluster-admin ClusterRole授予用户user1,user2和group1,用以下命令就行。

kubectl create clusterrolebinding cluster-admin –clusterrole=cluster-admin –user=user1 –user=user2 –group=group1

访问主体中除了常用的用户,组以外,还有一类叫做服务账号,service account。service account是k8s为pod内部的进程访问apiserver创建的一种用户。因为是pod里面的,所以也会对应各自的命名空间。

在k8s中设计了一种资源对象叫做Secret,分为两类,其中一类是用于记录ServiceAccount的service-account-token。

我们看看kube-system中的secret存储的serviceaccount信息。

阿里云k8s和自建k8s区别_mesos k8s_k8s认证

可以看到很多serviceaccount name,每个name下都有3个标识,分别是Token、ca.crt、namespace。

token是使用API Server私钥签名的JWT。用于访问API Server时,Server端认证。

ca.crt,根证书。用于Client端验证API Server发送的证书。

namespace, 标识这个service-account-token的作用域名空间,这里的namespace就是kube-system。

我们着重挑default这个账号来看。

k8s认证_阿里云k8s和自建k8s区别_mesos k8s

账号名在-token前,就叫default。

我们给这个服务账号绑定角色。

kubectl create clusterrolebinding default-admin –clusterrole=cluster-admin –serviceaccount=kube-system:default

查看绑定,我们把这个账号赋予新角色名default-admin,成功绑定到集群角色cluster-admin了,这就意味着我们的default这个serviceaccount拥有了集群最高权限,自然以它建立的pod也是集群最高权限的pod。

k8s认证_mesos k8s_阿里云k8s和自建k8s区别

mesos k8s_阿里云k8s和自建k8s区别_k8s认证

关于RBAC、账号、角色、命名空间的内容就说到这里,如果比较混乱的话结合后面的攻击利用相信会很快理解。

四、k8s的攻击利用

终于枯燥的概念说完了,我们就来说说关于k8s的攻击方式的利用。从前面的概念我们不难看出,k8s的本身还是比较安全的。当前k8s的攻防利用主要以权限配置不当造成未授权来进行攻击,或者是通过容器漏洞进入容器后形成逃逸。

为了演示搭了个环境,后续内容请结合环境的地址和端口观看。

Master节点

192.168.41.22

Worker节点1

192.168.41.23

有一个nginx演示pod

Worker节点2

192.168.41.24

4.1 未授权访问

未授权问题是目前k8s存在最多的问题,也是各大公网蠕虫的必争之地。以下是常见的k8s未授权:

未授权访问端口

功能

利用方式

6443,8080

kube-apiserver

未授权访问获取kube-system的token,通过kubectl使用kube-system的token获取pod列表。之后可进一步创建pod或控制已有pod进行命令执行等操作。

10250,10255

kubelet

kubeletctl批量获取pod等信息,尝试获取pod内/var/run/secrets/kubernetes.io/serviceaccoun/的token

2379

etcd

导出全量etcd配置,获取k8s认证证书等关键信息,进而通过kubectl创建恶意pod或控制已有pod,后续可尝试逃逸至宿主机

30000以上

dashboard

配置问题导致可跳过认证进入后台

2375

docker

Docker daemon默认监听2375端口且未鉴权k8s认证,我们可以利用API来完成Docker客户端能做的所有事情。

4.1.1 apiserver未授权访问

apiserver有两个端口,8080和6443。现在的云服务商提供的容器默认已不存在8080端口,主要问题还是在6443端口上。

我们正常访问6443端口,会出现以下情况,我们默认访问的角色就是系统给的anonymous。

k8s认证_阿里云k8s和自建k8s区别_mesos k8s

当运维人员存在配置不当的情况下,就可能存在将”system:anonymous”用户绑定到”cluster-admin”用户组,从而使6443端口允许匿名用户以管理员权限向集群内部下发指令。

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

k8s认证_阿里云k8s和自建k8s区别_mesos k8s

当我们把system:anonymous绑定到cluster-admin的集群角色时,再来访问。即可看到能访问的内容。

阿里云k8s和自建k8s区别_k8s认证_mesos k8s

然后访问:6443/api/v1/namespaces/kube-system/secrets/ 获取kube-system命名空间的token信息。

这里有很多token,正好对应前面看到的所有kube-system命名空间中的服务账号。系统自带的服务账号没啥操作权限,你需要寻找运维人员自建的。总之,有admin就找admin,没有的话找个非系统自带账号或者尝试default账号。

为了演示,我给default账号赋予了一个cluster-admin的角色,我们利用它的token看看能做什么事。

kubectl create clusterrolebinding default-admin –clusterrole=cluster-admin –serviceaccount=kube-system:default

mesos k8s_阿里云k8s和自建k8s区别_k8s认证

拿到了token后,可以在攻击机上安装kubectl工具,然后执行以下命令创建一个test_config,token处填入你获取的 token

touch test_config

kubectl –kubeconfig=./test_config config set-credentials hacker –token=TOKEN

kubectl –kubeconfig=./test_config config set-cluster hacked_cluster –server=https://192.168.41.22:6443/ –insecure-skip-tls-verify

kubectl –kubeconfig=./test_config config set-context test_context –cluster=hacked_cluster –user=hacker

kubectl –kubeconfig=./test_config config use-context test_context

通过kubectl加载刚才的config文件执行pod里面的命令

kubectl –kubeconfig=./test_config get nodes -A

k8s认证_阿里云k8s和自建k8s区别_mesos k8s

看,很轻松就接管了集群,后续直接参考kuectl的操作手册进行操作。

4.1.2 kubelet未授权访问

每一个Node节点都有一个kubelet服务,kubelet监听了10250,10248,10255等端口。

正常情况下访问是这样的:

:10250/pods

为了演示,我把kubelet的配置文件中anonymous认证改成true(默认是false)

mesos k8s_k8s认证_阿里云k8s和自建k8s区别

重启服务后再次访问。

k8s认证_mesos k8s_阿里云k8s和自建k8s区别

这个又怎么利用呢?

我们可以在攻击机上下载kubeletctl工具

在攻击机上执行下面命令:

./kubeletctl pods -s 192.168.41.23 –port 10250

k8s认证_mesos k8s_阿里云k8s和自建k8s区别

可以看到pod,namespace,containers。

使用命令

curl -k :10250/run/$namespace/$POD/$CONTAINERS -d “cmd=ls” –insecure

就能执行pod里容器的命令。

curl -k :10250/run/default/nginx-f89759699-tct4p/nginx -d “cmd=ls” –insecure

阿里云k8s和自建k8s区别_mesos k8s_k8s认证

既然可以执行容器命令,后续可以尝试容器逃逸,逃逸的方式我们后面再说。

如果实战中发现的是10255端口的未授权而非10250,它是只读端口,无法直接利用在容器中执行命令,但是可以获取环境变量ENV、主进程CMDLINE等信息,里面包含密码和秘钥等敏感信息的概率是很高的,可以快速帮我们在对抗中打开局面。

4.1.3 etcd未授权访问

etcd默认监听了2379等端口,如果2379端口暴露到公网,可能造成敏感信息泄露。etcd若存在未授权,攻击者导出全量etcd配置,获取k8s认证证书等关键配置,进而通过kubectl创建恶意pod或控制已有pod,后续可尝试逃逸至宿主机。

访问:2379/v2/keys,有内容,类似{“action”:“get”,“node”:{“dir”:true}} 这样的,就确定存在未授权访问。

mesos k8s_阿里云k8s和自建k8s区别_k8s认证

攻击机从下载 得到etcdctl。通过如下命令可以遍历所有的key:

ETCDCTL_API=3 ./etcdctl –endpoints=http://IP:2379/ get / –prefix –keys-only

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: wxii2p22