标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2025-2838] 作者: 浩丶轩 发表于: [2021-03-02] [2021-03-02]被用户:浩丶轩 修改过
本文共 [712] 位读者顶过
6. 容器相关组件的历史漏洞
2020年我们和腾讯云的同学一起处理跟进分析了多个官方开源分支所披露的安全问题,并在公司内外的云原生能力上进行复现、分析,从产品和安全两个角度出发探讨攻击场景,保障云用户和业务的安全。
[出自:jiwo.org] 其中投入时间比较多的,主要是以下十个漏洞,每个都非常有趣,且都在云产品上得到了妥善的跟进和安全能力建设: ![]()
实际攻防场景里面我真实用过且在关键路径里起到作用的也就 CVE-2020-15257,其它漏洞的POC都只在漏洞公开时自建测试的环境复现和公司内服务的漏洞挖掘用了一下,有些环境虽然有漏洞,但是实际打真实目标却没怎么用得上。
值得一提的是最开始跟进分析时,因为EXP需要钓鱼让管理员去执行 docker exec 或 kubectl exec 才可以触发,所以不怎么看好的 CVE-2019-5736 RUNC 容器逃逸漏洞;反而是真的遇到几个无交互即可触发的场景。主要是 vscode server、jupyter notebook、container webconsole 等这种提供容器内交互式shell的多租户场景在企业内网里变多了,容器逃逸之后就是新的网络环境和主机环境。 7. 容器、容器编排组件API配置不当或未鉴权
就安全问题来说,业界普遍接触最多、最首当其冲的就是容器组件服务的未鉴权问题。我们在2019年的时候整理了一份Kubernetes架构下常见的开放服务指纹,提供给到了地表最强的扫描器洞犀团队,就现在看来这份指纹也是比较全的。
前六个服务的非只读接口我们都曾经在渗透测试里遇到并利用过,都是一旦被控制可以直接获取相应容器、相应节点、集群权限的服务,也是广大公网蠕虫的必争之地。 7.1. 组件分工
各个组件未鉴权所能造成的风险,其实从它们在Kubernetes集群环境里所能起到的作用就能很明显的判断出来,如 APIServer 是所有功能的主入口,则控制 APIServer 基本上等同控制集群的所有功能;而 kubelet 是单个节点用于进行容器编排的 Agent,所以控制 kubelet 主要是对单个节点下的容器资源进行控制。
组件分工上较为完整的图例可参考: ![]()
想必这样也相对晦涩难懂,我简化了一下,假如用户想在集群里面新建一个容器集合单元,那各个组件以此会相继做什么事情呢?
1. 用户与 kubectl 或者 Kubernetes Dashboard 进行交互,提交需求。(例: kubectl create -f pod.yaml);
2. kubectl 会读取 ~/.kube/config 配置,并与 apiserver 进行交互,协议:http/https;
3. apiserver 会协同 ETCD 等组件准备下发新建容器的配置给到节点,协议:http/https(除 ETCD 外还有例如 kube-controller-manager, scheduler等组件用于规划容器资源和容器编排方向,此处简化省略);
4. apiserver 与 kubelet 进行交互,告知其容器创建的需求,协议:http/https;
5. kubelet 与Docker等容器引擎进行交互,创建容器,协议:http/unix socket. 至此我们的容器已然在集群节点上创建成功,创建的流程涉及ETCD、apiserver、kubelet、dashboard、docker remote api等组件,可见每个组件被控制会造成的风险和危害,以及相应的利用方向;
对于这些组件的安全性,除了不同组件不一样的鉴权设计以外,网络隔离也是非常必要的,常规的 iptables 设置和规划也可以在容器网络中起到作用(容器网络的很多能力也是基于 iptables 实现的)。
另外比较有容器特色的方案就是 Network Policy 的规划和服务网格的使用,能从容器、POD、服务的维度更加优雅的管理和治理容器网络以及集群内流量。这些组件的资料和对应渗透手法,这里我们一一介绍一下: 7.2. apiserver
如果想要攻击 apiserver, 下载 kubectl 是必经之路。
curl -LO "https://dl.Kubernetes.io/release/$(curl -L -s https://dl.Kubernetes.io/release/stable.txt)/bin/linux/amd64/kubectl"
默认情况下,apiserver 都是有鉴权的: ![]()
当然也有未鉴权的配置:kube-apiserver --insecure-bind-address=0.0.0.0 --insecure-port=8080,此时请求接口的结果如下:
对于这类的未鉴权的设置来说,访问到 apiserver 一般情况下就获取了集群的权限:
可能还有同学不知道 apiserver 在 Kubernetes/容器编排集群里的重要地位,这里简单介绍一下:在蓝军眼中的 Kubernetes APIServer其重要性,如下图:
所以,对于针对Kubernetes集群的攻击来说,获取 admin kubeconfig 和 apiserver 所在的 master node 权限基本上就是获取主机权限路程的终点。
至于如何通过 apiserver 进行持续渗透和控制,参考 kubectl 的官方文档是最好的: https://Kubernetes.io/docs/reference/generated/kubectl/kubectl-commands 7.3. kubelet
每一个Node节点都有一个kubelet服务,kubelet监听了10250,10248,10255等端口。
其中10250端口是kubelet与apiserver进行通信的主要端口,通过该端口kubelet可以知道自己当前应该处理的任务,该端口在最新版Kubernetes是有鉴权的,但在开启了接受匿名请求的情况下,不带鉴权信息的请求也可以使用10250提供的能力;因为Kubernetes流行早期,很多挖矿木马基于该端口进行传播和利用,所以该组件在安全领域部分群体内部的知名度反而会高于 APIServer。
在新版本Kubernetes中当使用以下配置打开匿名访问时便可能存在kubelet未授权访问漏洞: ![]()
如果10250端口存在未授权访问漏洞,那么我们可以先使用/pods接口获取集群的详细信息,如namespace,pods,containers等
之后再通过 curl -k https://Kubernetes-node-ip:10250/run/// -d “cmd=id” 的方式在任意容器里执行命令 ![]()
此时,选择我们所有控制的容器快速过滤出高权限可逃逸的容器就很重要,在上述 /pods API 中可以获取到每个 POD 的配置,包括了 host*、securityContext、volumes 等配置,可以根据容器逃逸知识快速过滤出相应的POD进行控制。
由于这里10250鉴权当前的Kubernetes设计是默认安全的,所以10255的开放就可能更加容易在红蓝对抗中起到至关重要的作用。10255 本身为只读端口,虽然开放之后默认不存在鉴权能力,无法直接利用在容器中执行命令,但是可以获取环境变量ENV、主进程CMDLINE等信息,里面包含密码和秘钥等敏感信息的概率是很高的,可以快速帮我们在对抗中打开局面。 7.4. dashboard
dashboard是Kubernetes官方推出的控制Kubernetes的图形化界面,在Kubernetes配置不当导致dashboard未授权访问漏洞的情况下,通过dashboard我们可以控制整个集群。
在dashboard中默认是存在鉴权机制的,用户可以通过kubeconfig或者Token两种方式登录,当用户开启了enable-skip-login时可以在登录界面点击Skip跳过登录进入dashboard ![]()
然而通过点击Skip进入dashboard默认是没有操作集群的权限的,因为Kubernetes使用RBAC(Role-based access control)机制进行身份认证和权限管理,不同的serviceaccount拥有不同的集群权限。
我们点击Skip进入dashboard实际上使用的是Kubernetes-dashboard这个ServiceAccount,如果此时该ServiceAccount没有配置特殊的权限,是默认没有办法达到控制集群任意功能的程度的。
但有些开发者为了方便或者在测试环境中会为Kubernetes-dashboard绑定cluster-admin这个ClusterRole(cluster-admin拥有管理集群的最高权限)。
这个极具安全风险的设置,具体如下:
1. 新建dashboard-admin.yaml内容如下(该配置也类似于“利用大权限的 Service Account”一小节的配置 )
2. 执行kubectl create -f dashboard-admin.yaml 此时用户通过点击Skip进入dashboard即可拥有管理集群的权限了。 ![]()
进入到dashboard我们可以管理Pods、CronJobs等,这里介绍下我们如何通过创建Pod控制node节点。
我们新建一个以下配置的Pod,该pod主要是将宿主机根目录挂载到容器tmp目录下。 ![]()
之后我们便可以通过该容器的tmp目录管理node节点的文件。
值得注意的是,为了集群的稳定性和安全性要求,在Kubernetes默认设计的情况下Pod是不能调度到master节点的,但如果用户自行设置关闭了Master Only状态,那么我们可以直接在master节点新建Pod更直接的控制master node;不过目前各大主流云产商上的Kubernetes集群服务,都会默认推荐让Master节点由云厂商托管,更加加剧了Master节点渗透和控制的难度 。 7.5. etcd
etcd被广泛用于存储分布式系统或机器集群数据,其默认监听了2379等端口,如果2379端口暴露到公网,可能造成敏感信息泄露,本文我们主要讨论Kubernetes由于配置错误导致etcd未授权访问的情况。Kubernetes默认使用了etcd v3来存储数据,如果我们能够控制Kubernetes etcd服务,也就拥有了整个集群的控制权。
在Kubernetes中用户可以通过配置/etc/Kubernetes/manifests/etcd.yaml更改etcd pod相关的配置,倘若管理员通过修改配置将etcd监听的host修改为0.0.0.0,则通过ectd获取Kubernetes的认证鉴权token用于控制集群就是自然而然的思路了,方式如下:
首先读取用于访问apiserver的token ![]()
利用token我们可以通过apiserver端口6443控制集群:
7.6. docker remote api
Docker Engine API是Docker提供的基于HTTP协议的用于Docker客户端与Docker守护进程交互的API,Docker daemon接收来自Docker Engine API的请求并处理,Docker daemon默认监听2375端口且未鉴权,我们可以利用API来完成Docker客户端能做的所有事情。
Docker daemon支持三种不同类型的socket: unix, tcp, fd。默认情况下,Docker daemon监听在unix:///var/run/docker.sock,开发者可以通过多种方式打开tcp socket,比如修改Docker配置文件如/usr/lib/systemd/system/docker.service: ![]()
之后依次执行systemctl daemon-reload、systemctl restart docker便可以使用docker -H tcp://[HOST]:2375这种方式控制目标docker
因此当你有访问到目标Docker API 的网络能力或主机能力的时候,你就拥有了控制当前服务器的能力。我们可以利用Docker API在远程主机上创建一个特权容器,并且挂载主机根目录到容器,对主机进行进一步的渗透,更多利用方法参考容器逃逸章节。
检测目标是否存在docker api未授权访问漏洞的方式也很简单,访问http://[host]:[port]/info路径是否含有ContainersRunning、DockerRootDir等关键字。 7.7. kubectl proxy
kubectl proxy这个子命令大家可能遇到比较少,这里单独介绍一下;由于上述几个组件的安全问题较为常见和出名,且在目前开源分支里它们在鉴权这个方面都是默认安全的,所以直接出现问题的可能性较小,企业在内外网也都收敛得不错;此时 kubectl proxy 这个子命令反而是另一个常见且蠕虫利用起来非常简单粗暴的问题。
了解使用过Kubernetes的同学应该知道,如果你在集群的POD上开放一个端口并用ClusterIP Service绑定创建一个内部服务,如果没有开放NodePort或LoadBalancer等Service的话,你是无法在集群外网访问这个服务的(除非修改了CNI插件等)。 ![]()
如果想临时在本地和外网调试的话,kubectl proxy 似乎是个不错的选择。
但其实 kubectl proxy 转发的是 apiserver 所有的能力,而且是默认不鉴权的,所以 --address=0.0.0.0 就是极其危险的了。
8. 容器镜像安全问题
容器镜像的安全扫描能力是很多乙方商业产品和甲方安全系统首先会推进的容器安全建设方向。不像容器运行时安全监控需要较高的成本、稳定性要求和技术积累,也有业界相对成熟的开源方案。
容器镜像是容器安全非常关键且重要的一环,当获取到节点权限或管理员PC权限时,~/.docker/config.json 文件内就可能存有镜像仓库账号和密码信息,用户名和密码只用 Base64 编码了一下,对于安全人员来说和没有是一样的。 ![]()
很多POD和线上容器在使用镜像时,可能用 latest 或默认没有指定版本,所以劫持镜像源之后只要在原本的 latest 之上植入恶意代码并 push 新的版本镜像,就可以在获取镜像权限之后进而获取线上的容器权限。
不仅在安全攻防领域,作为一个长期依赖容器技术的半吊子开发者,我也不建议用 latest 镜像标签作为线上环境的长期方案;从研发运维角度的最佳实践来看,使用特定版本的TAG且可以和代码版本控制相对应是比较推荐的方案,应该保障每个镜像都是可追踪溯源的。
比较有趣的是,我们曾经遇到企业在基础容器镜像里打入 sshd 并且在 init.sh 主程序中启动 sshd 程序(无论是安全还是容器架构最佳实践都是不建议的),导致所有Kubernetes集群里的容器都会开放22端口并且拥有一样的/etc/shadow文件和/root/.ssh/authorized_keys。这就代表所有的容器都可以使用一个通用密码和ssh证书去登录。因此在逃逸获取容器的宿主机权限后,分析容器基础镜像的通用安全问题确实可以很快扩大影响面。 9. 二次开发所产生的安全问题
9.1. 对Kubernetes API的请求转发或拼接
熟悉Kubernetes架构的同学可能知道,管理员管理Kubernetes无论是使用 kubectl 或 Kubernetes dashboard 的UI功能,其实都是间接在和 APIServer 做交互。
参考官方的架构图: ![]()
那么如果需求需要在Kubernetes原本的能力上做开发的话,很有可能产品后端就是请求了 APIServer 的 Rest API 实现的。
攻击者破坏程序原本想对 APIServer 所表达的语义,注入或修改 Rest API 请求里所要表达的信息,就可以达到意想不到的效果。
例如下面的代码,用户传入 namespace、pod和容器名即可获取相应容器的日志: ![]()
相似的需求和API还有例如:
1. 到用户自己的容器内创建一个 web console 供用户进行远程调试, POST https:/apiserver:
8443/api/v1/namespaces/default/pods/nginx/exec?command=bash&container=nginx&stdin=true&stdout=true&tty=true
2. 给用户销毁自己POD的能力, DELETE https://apiserver:
8443/api/v1/namespaces/default/pods/sleep-75c6fd99c-g5kss
这类型的需求在多租户的集群设计里比较常见。渗透测试选手看到这样的代码或API,首先想到的就是越权,把 namespace、pod和容器名修改为他人的,就可以让二次开发的代码去删除其他用户的POD、进入其他用户的容器里执行命令、获取其它POD的日志等。
除了上述的功能点,这里比较容易出问题且影响较大的功能和业务逻辑是多租户集群平台的自研 Web Console功能,Web Console的越权问题可以直接导致任意容器登录和远程控制,也是非常值得关注的一个点。
其实我们甚至可以修改获取日志、删除POD、执行命令的 Rest API 语义:
例如在上述 namespace 命名空间处插入 “default/configmaps/istio-ca-root-cert?ingore=”,
原本请求的
"https://apiserver:6443/api/v1/namespaces/istio-dev/pods/service-account-simple/lo g?container=test-container"
就会转变为
"https://apiserver:6443/api/v1/namespaces/default/configmaps/istio-ca-root-cert?ingore=/pods/service-account-simple/lo g?container=test-container",
实际就是请求了
https://apiserver:6443/api/v1/namespaces/default/configmaps/istio-ca-root-cert,从获取日志转变了为获取 configmap。
10. Serverless
Serverless还有一个比较大漏洞挖掘的方向是资源占用,例如驻留进程,驻留文件,进程偷跑,句柄耗尽等条件竞争漏洞,用于影响多租户集群,占用计算资源等。我们之前也研究过相关的安全漏洞和利用方法,但因为和传统的黑客攻防对抗相关性较少,此处暂且不表。
这里只描述那些确实成为安全演习关键路径一环的漏洞。
有些Serverless实现在应用程序生命周期结束之后,程序文件的清理上进入了僵局。一方面开发者希望借助容器“对Linux Cgroup和Namespace进行管理的特性”用于实现限制应用的资源访问能力和进程权限的需求;在此之上,开发者希望能更快的达到用户文件清理的目的,避免反复初始化容器环境带来的时间和资源上的消耗,复用同一个容器环境。
而在蓝军的视角里,这样的处理方式会导致多个用户的应用会存在多个用户在不同时间段使用一个容器环境的情况,在安全性上是比较难得到保障的。
以面向Python开发者的Serverless架构为例,开发者所构想的简化模型是这样的:
用户文件清理的代码实现上,简化可参考:
在进行包括上述文件删除动作在内的一系列环境清理工作之后,容器内外的主调度进程会写入其他租户的代码到当前容器内,此时这个容器就进入了下一个应用的Serverless生命周期。
虽然,主框架代码实现内有很多类似调用系统命令拼接目录等参数进行执行的代码实现,但是类似命令注入的问题大多只能影响到当前的生命周期;而又因为用户权限的问题,我们没办法修改其他目录下的文件。
于是我们构建了这样一个目录和文件:
当程序执行 rm -rf * 时,因为 bash glob 对 * 号的返回是有默认排序的,这里可参考下方 bash 的文档,只要我们不去修改 LC_ALL 的环境变量,我们构造的 --help 文件会排列在文件列表的最前方,导致 rm 会执行 rm --help 而终止,恶意文件得以保留。
Pathname Expansion
After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern.
我们可以简单在 bash 内进行验证,可以看到 rm -rf * 命令被 --help 强行终止,我们所植入的恶意文件还依然存在没有被清理掉,同时 rm --help 的命令执行返回为 0,不会产生 OS ERROE Code,清理进程会认为这里的清除命令已经成功执行:
而实际在serverless log里的返回,可参考:
此时,serverless的主调度程序会以为自己已经正常清理了容器环境,并写入另外一个租户的源码包进行执行,而当另外一个租户的代码执行至 import requests 时,我们驻留在应用目录下的 requests.py 内的恶意代码就会被执行。
不过值得注意的是,因为 serverless 的生命周期一般极为有限,所以此时获取的shell可能会在短时间结束,触发新一轮的反弹shell,且Servless容器环境内的信息相对单一和简便。所以容器环境里值得我们探索和翻找的地方也不多,一般需要关注:]
新的代码
代码内部配置
环境变量
秘钥、证书、密码信息等
不同的serverless架构实现对于存储和传递相应信息的方式各有不同。
现在我们知道了,很多Serverless的用户代码都跑在一个个容器内。不同应用的代码运行于不同的容器之上,依靠容器原本的能力进行资源回收和隔离。由于Serverless应用的代码会进行相应的结构化解耦,且每个应用容器的底层环境相对来说是一致的。所以其实,根据应用漏洞获取更多应用类Serverless容器不仅困难而且在内网渗透中作用相对较为有限,能做的事情也相对较少。
但其实在不同的 Serverless 架构中,都有多类持久化且公用的容器以实现程序调度、代码预编译、代码下载运行等逻辑。
这类容器一般拥有获取所有用户代码、配置和环境变量的能力,同时也比较容易出现 Docker IN Docker或大权限 Service Account的设计。
如何控制这类型的容器呢?以下是我们在攻防过程中遇到的场景:
1. 在下载源代码时,使用 git clone 进行命令拼接,导致存在命令注入;
2. 在安装 node.js 依赖包时,构造特殊的 package.json 利用 preinstall 控制公用容器。
3. 配置指向恶意第三方仓库的 pip requirements.txt,利用恶意 pip 包获取依赖打包容器的权限,同类的利用手法还可以作用于nodejs、ruby等语言的包管理器。
4. 因为容器镜像里的打了低版本git、go等程序,在执行 git clone, git submodule update(CVE-2019-19604), go get 时所导致的命令执行,
下图为 CVE-2018-6574 的 POC 可参考: https://github.com/neargle/CVE-2018-6574-POC/blob/master/main.go。
11. DevOps
我们从2019年开始研究 DevOps 安全攻防对抗的战场,不仅研究企业内部 DevOps 平台和产品的安全性,同时也不断在内部的研发流程中积极引入 DevOps 做蓝军武器化自动化研发的测试、发布、打包和编译等流程中。
从蓝军的角度,在我们历史攻防对抗中比较值得注意的场景有以下几点:
1. 目前不同的DevOps平台可能会包含不同的 Low-Code 流水线特性,隔离上也会大量采用我们上面提及的多租户容器集群设计,所以多租户集群下的渗透测试技巧也大致无二。
2. 控制了上述的多租户容器集群是可以控制集群所用节点服务器的,这些服务器的作用一般用于编译和构建业务代码,并接入代码管理站点如 Gitlab、Github等,所以一般拥有获取企业程序各业务源码的权限。
3. DevOps 及其相关的平台其最重要的能力之一就是 CICD,因此控制 DevOps 也就间接拥有了从办公网、开发网突破进入生产网的方法;控制的应用数量和业务种类越多,也能根据应用的不同进入不同的隔离区。
另外在DevOps平台内若集成了日志组件(云原生的重点之一:可观察性)的话,那么日志组件和Agent的升级、安装问题一般会是重中之重,蓝军可以根据这个点达到获取公司内任意主机权限的目地。
作为API网关,它具有管理集群南北流量的功能,一般也可能作为集群流量的入口和出口(ingress/egress)。而作为标榜云原生特性的API网关产品,似乎无一例外都会具有动态配置、灵活修改、远程管理的特性,而这些特性往往以 REST API 对外提供服务。
然而在远程配置逻辑的鉴权能力上,身为网关这种基础网络的产品,各个受欢迎的开源组件在默认安全的实现上似乎还需努力。
以 Kong 为例,Kong API 网关 (https://github.com/Kong/kong) 是目前最受欢迎的云原生 API 网关之一,有开源版和企业版两个分支,被广泛应用于云原生、微服务、分布式、无服务云函数等场景的API接入中间件,为云原生应用提供鉴权,转发,负载均衡,监控等能力。
我们曾经在一次渗透测试中使用Kong的远程配置能力突破外网进入到内网环境中,可以参考之前的预警文章《腾讯蓝军安全提醒:开源云原生API网关 Kong 可能会成为攻击方进入企业内网的新入口》
Kong 使用 Kong Admin Rest API 作为管理 Kong Proxy 能力的关键入口,以支持最大程度的灵活性;在开源分支里,这个管理入口是没有鉴权能力的(Kong企业版支持对 Kong Admin Rest API 进行角色控制和鉴权),Kong建议用户在网络层进行访问控制;当攻击方可以访问到这个 API,他就具有了 Kong Proxy 的所有能力,可以查看和修改企业当前在南北流量管理上的配置,可以直接控制 API 网关使其成为一个开放性的流量代理(比SSRF更便于使用和利用);从攻击方的角度思考,控制了这个 API 等于是拥有了摸清网络架构和打破网络边界的能力。
当蓝军可以访问到 Kong Admin Rest API 和 Kong Proxy 时,蓝军可以通过以下步骤创建一个通往内网的代理:
至此,蓝军从外网发往 Kong Proxy 的流量只要 host 头带有 target.com 就会转发到内网的 target.com:443 中,实际利用手法会根据内网和目标站点配置的不同而变化。
而目前 Kong 的开源分支里是不支持给 Kong Admin Rest API 添加相应的鉴权能力的,只可以改变监听的网卡,或使用设置 Network Policy、 iptables、安全组等方式进行网络上隔离。现在最常见的方式就是不开放外网,只允许内网访问。也因为如此,如果已经进入到内网,API 网关的管理接口会成为我首要的攻击目标之一,借此我们可以摸清当前集群对内对外提供的相关能力,更有可能直接获取流量出入口容器的Shell权限。
另外一个值得深入的开源组件就是Apache APISIX,这是一款基于lua语言开发,是一个动态、实时、高性能的 API 网关, 提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。
APISIX提供了REST Admin API功能,用户可以使用REST Admin API来管理APISIX,默认情况下只允许127.0.0.1访问,用户可以修改conf/config.yaml中的allow_admin字段,指定允许调用Admin API的ip列表。
当用户对外开启了Admin API且未修改硬编码的缺省admin_key的情况下,攻击者可以利用该admin_key执行任意lua代码。
根据apisix官方文档可以知道,在创建路由时用户可以定义一个filter_func参数用于处理请求,filter_func的内容可以是任意的lua代码。
那么我们便可以使用默认的admin_key创建恶意的route并访问以触发lua代码执行,达到rce的目的,下面是具体步骤:
(1)创建可用的services:
(2)创建恶意的route:
最后访问 http://127.0.0.1:9080/api/tforce_test 即可触发预定义的lua代码执行。
因此,在内网里攻击云原生API网关是比较容易打开一定局面的。
13.1. 从 CronJob 谈持久化
因为 CronJob 的设计和 Linux CronTab 过于相似,所以很多人都会把其引申为在Kubernetes集群攻击的一些持久化思路。
官方文档
https://Kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ 里也谈及了 CronJob 和 CronTab 的对比, 这个技术也确实可以和 CronTab 一样一定程度上可以满足持久化的场景。
这里有一个我们预研时使用的 CronJob 配置:
此处的配置会隔每分钟创建一个具有生命周期的POD,同时这些容器也可以使用特权容器(如上述配置)、挂载大目录等设置,此时持久化创建的 POD 就可以拥有特权和访问宿主机根目录文件的权限。
不过实际对抗过程中,虽然我们也会对恶意的POD和容器做一定的持久化,但是直接使用 CronJob 的概率却不高。在创建后门POD的时候,直接使用 restartPolicy: Always 就可以方便优雅的进行后门进程的重启和维持,所以对 CronJob 的需求反而没那么高。
|