f10@t's blog

K8s攻防之OWASP-K8S-TOP10(下)

字数统计: 2.8k阅读时长: 10 min
2023/10/04

紧接上一篇,继续学习剩下的漏洞类型。(ps:上一次的环境有一些问题,我重新用ubuntu20搭建了。如果也有学习这块但嫌环境麻烦的小伙伴,可以私信我要虚拟机,联系方式见头像下方,一起学习和讨论。

剩下的K5-K10主要是开发人员在k8s网络配置、资源配置文件、开发程序打包时存在的一些配置问题

K06: Broken Authentication Mechanisms

定义

k8s中对于资源的访问都是需要api server的统一认证的,如下图所示,通常有两种访问形式:

  • 直接访问
  • pod内访问

前者通常是开发人员需要调试程序的场景,可以使用包括OpenID Connect (OIDC)、证书等方法。而后者通常上是使用一个ServiceAccount Token进行访问。然而上述方式在使用的时候有一些注意事项和最佳实践

避免使用证书作为认证的手段

虽然使用证书向k8s api认证很方便,但因为在当前k8s中,API无法撤销一个证书,因而客户端私钥的泄露会导致很大的问题,且证书的配置、签名和分发也非常麻烦。因此建议不要将证书作为主要的认证手段。

不要引入自己定义的认证方式

尽量使用广泛使用的、支持的认证方式。

必要时使用多因子认证

对于人直接访问的情况,采用多因子认证手段,额外添加如OIDC等认证方式辅助。

这里也有一个攻击案例,由于开发人员将.kubeconfig文件泄露到了github上,其中包含了访问k8s的令牌,当攻击者从github上发现该令牌后,由于该开发人员的k8s集群只设置了使用证书的认证方式,没有第二个辅助认证方式,因而导致了直接被访问的情况。

不要从集群外使用ServiceAccount的Token

默认情况下,从集群外部访问所使用的SA Token是由Kubernetes Secret生成的且没有过期时间,对集群带来了一定风险。因为推荐使用kubectl create token添加--duration flag来生成Token。

使用短期(short-lived)令牌验证用户和外部服务

很好理解,令牌存活时间越短,泄漏后带来的潜在威胁也就越小。

对应k8s-goat场景:RBAC least privileges misconfiguration

本场景与K03场景相同,可以参考上篇内容:K03-overly-permisive-rbac-K8s攻防之OWASP-K8S-TOP10(上) · f10@t's blog (f10at.cn)

该攻击方法从战术上属于Credential Access,技术上包含List K8S secretsContainer service account

这里在K06中想要强调的,我理解是:

  1. 使用证书作为认证手段,当我们拥有了一个pod的命名执行后,就意味着私钥已经泄露了。若仅使用证书作为主要的认证手段,则在该请款下,k8s API无法撤销一个证书。
  2. 没有设置合理的令牌存活时间。

参考学习

K07: Missing Network Segmentation Controls

定义

kubernetes networking is flat by default. Meaning that, when no additional controls are in place any workload can communicate to another without constraint.

k8s默认情况下,各个pod之间的流量都是打通的,没有任何限制,因而攻击者就可以在这个"内网"中肆意妄为了。

为了解决上述问题,我们需要网络分割(network segmentation)来限制攻击者的活动空间。有如下四种可行的方式:

  • k8s原生方案(Native Controls):
    • Multi-Cluster:直接从真是网络上进行划分,将集群进行隔离,显然是可行的,但是会增大工程复杂度。
    • NetworkPolicies:成熟做法,通过编写配置文件即可实现细颗粒度的流量筛选。下面学习该方式。
  • 服务网格(Service Mesh):由于服务网格方案如Istio中,将熔断、限流等流量控制方面的措施与上层业务解耦下沉,因而也可以基于该方案进行流量筛选。如Istio中的AuthorizationPolicy资源。
  • CNI插件

对应k8s-goat场景:Kubernetes namespaces bypass

下面是官方的攻击示意图。初步判断低手通过切换命名空间,并利用redis的6379端口访问到了其中的的资源。

该场景攻击涉及到端口扫描和访问其他命名空间资源,分别涉及战术Discovery中的Network Mapping技术,以及战术Lateral Movement中的Cluster internal networking技术。

首先我们需要启动一个默认命名空间内的容器用于提供命令执行:

我们的目标是访问secure-middleware命名空间内一个名为cache-store的pod中的k8s_goat_flag

利用

那其实这块本质上就是web中的信息收集了,我们需要找他对应的目标以及其上6379redis服务并访问。先看看ip:

ok,所在网段10.10.12.0/24,且提前预备好了nmap,那我们第一步用ping做主机存活判断:

找到了该服务所在ip为10.10.12.5,第二步骤判断其开放端口:

发现redis服务,那最经典的就是redis未授权访问,看看有没有这个问题:

6,且可以看到名为SECRETSTUFF的键,查看其内容:

好吧。那怎么解决这个问题呢?

问题原因

从利用过程中可以看出来,默认情况下k8s没有对网络流量进行过滤,从而导致了我们可以实施发现、利用和访问的操作。

因此我们需要利用CNI设置网络策略(Network Policy)以实现网络边界的效果。在官方的另一个场景中,展示了如何创建NetworkPolicy文件,下面是补充内容:

补充:k8s-goat对应场景:Secure Network Boundaries using NSP

下面我们写一个网络策略配置文件以解决上面场景中存在的问题。(ps:当时,讲道理其实解决redis问题,这里我们主要关注于网络。官方的指导文档:Network Policies | Kubernetes

大前提,你所用的网络插件必须支持NetworkPolicy,这里我用的是Flannel。

预备知识

k8s的NSP可以使用如下三元素标识一个对象(entity)的策略:

  • 可允许访问本地资源的pod(除了自己)
  • 可允许访问本地资源的Namespace
  • IP黑名单

从上到下分别对应:PodNamespaceIP三个范畴。前两者可以通过Selector来定义,IP则使用CIDR范围来标识。

在编写具体配置时,我们使用的是ingressegress两个关键字,分别代表针对相对当前对象的流入流出的流量的策略,且都是白名单,即只有这两类字段下类型的流量是允许的。

下面是k8s官方的一个例子及含义

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
29
30
31
32
33
34
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy # 这是一个网络策略的配置文件
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes: # 所涉及的、将要被定义的流量类型。一共就这两种
- Ingress
- Egress
ingress: # 对于进入的流量而言:
- from: # from字段打头,可以定义如上所述的三种类型
- ipBlock: # 允许进入的CIDR
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector: # 允许进入的Namespace
matchLabels:
project: myproject
- podSelector: # 允许进入的Pod
matchLabels:
role: frontend
ports: # 上述策略所针对的本地端口
- protocol: TCP
port: 6379
egress: # 对于流出的流量而言
- to: # to字段打头
- ipBlock: # 允许流出的CIDR
cidr: 10.0.0.0/24
ports: # 上述策略所针对的远程端口
- protocol: TCP
port: 5978

解决K07场景中存在的问题

下面我们写一个网络策略文件,禁止任何外部流量访问本地的redis服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: solve-k07-redis-problem
namespace: secure-middleware
spec:
podSelector:
matchLabels:
app: cache-store
policyTypes:
- Ingress
ingress:
- from: # 啥都不写,即没有允许的
ports:
- protocol: TCP
port: 6379

应用到网络中:

删除k07中的pod,自动重启后即可发现已经无法访问这个端口了,从而实现网络隔离的效果。

这里有一些可以参考使用的网路配置文件:ahmetb/kubernetes-network-policy-recipes: Example recipes for Kubernetes Network Policies that you can just copy paste (github.com)

参考学习

K08: Secrets Management Failures

定义

这个比较好理解,k8s允许我们定义一些比如Secret类型的隐私资源,如下图中的数据库用户名和密码、Secret资源。

辣肯定不能靠k8s默认的base64这种简单的编码来存储了。因此我们需要保证配置文件中权限的最小化原则,并打开日志记录。

对应k8s-goat场景:Sensitive keys in codebases

下面是官方的攻击示意图,初步判断是应用程序在打包时,误将.git这样的敏感目录打包了,泄露了提交历史和文件内容。

访问对应端口:

我们的目标是找到aws_access_key_idaws_secret_access_key以及k8s-goat-FLAG

利用

其实就是web里的git泄露嘛,直接上工具git-dumper,然后就可以使用git命令查看了:

可以看到有一个分支注释中写了添加变量的字样,切换过去看一下:

问题原因

emmmm,说白了就是打包程序的时候眼窝睁大点就好了。

参考学习

K09: Misconfigured Cluster Components

定义

如上图所示,一些错误的组件配置可能会导致k8s集群安全性的大大降低,涉及组件如API Server、Kubelet、ETCD等。OWASP给了一些错误的配置示例:

Kubelet

--anonymous-auth=true

通常情况下,如使用kubectl命令时,我们需要认证才能请求kubelet,而若在kubelet服务启动时带上了该参数,那么任意的人都可以请求kubelet了,这显然是不安全的。

--authorization-mode=AlwaysAllow

同理,将AuthZ设置为AlwayAllow也将允许匿名的API访问。

ETCD

etcd中以键值对的方式、中心化地保存了k8s集群的数据,因而也要保护其安全。

Kube-apiserver

我理解主要是做好认证,毕竟它是K8S API请求的入口。

针对上述问题,可以选择使用CIS Kubernetes Benchmarks (cisecurity.org)进行扫描以检测错误的配置文件。

This CIS Benchmark is the product of a community consensus process and consists of secure configuration guidelines developed for Kubernetes. ——cisecurity.org

对应k8s-goat场景:KubeAudit - Audit Kubernetes clusters

这部分主要是借助开源工具kubeaudit对集群进行安全审计。

工具链接:Shopify/kubeaudit: kubeaudit helps you audit your Kubernetes clusters against common security controls (github.com)

参考学习

K10: Outdated and Vulnerable Kubernetes Components

定义

该场景因为利用的helm v2,现行的是v3。简单参考即可。

其实就是使用了带有漏洞的组件,如下图示意:

参考学习

CATALOG
  1. 1. K06: Broken Authentication Mechanisms
    1. 1.1. 定义
    2. 1.2. 对应k8s-goat场景:RBAC least privileges misconfiguration
    3. 1.3. 参考学习
  2. 2. K07: Missing Network Segmentation Controls
    1. 2.1. 定义
    2. 2.2. 对应k8s-goat场景:Kubernetes namespaces bypass
    3. 2.3. 利用
    4. 2.4. 问题原因
    5. 2.5. 补充:k8s-goat对应场景:Secure Network Boundaries using NSP
      1. 2.5.1. 预备知识
      2. 2.5.2. 解决K07场景中存在的问题
    6. 2.6. 参考学习
  3. 3. K08: Secrets Management Failures
    1. 3.1. 定义
    2. 3.2. 对应k8s-goat场景:Sensitive keys in codebases
    3. 3.3. 利用
    4. 3.4. 问题原因
    5. 3.5. 参考学习
  4. 4. K09: Misconfigured Cluster Components
    1. 4.1. 定义
    2. 4.2. 对应k8s-goat场景:KubeAudit - Audit Kubernetes clusters
    3. 4.3. 参考学习
  5. 5. K10: Outdated and Vulnerable Kubernetes Components
    1. 5.1. 定义
    2. 5.2. 参考学习