紧接上一篇,继续学习剩下的漏洞类型。(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 secrets
和Container service account
。
这里在K06中想要强调的,我理解是:
- 使用证书作为认证手段,当我们拥有了一个pod的命名执行后,就意味着私钥已经泄露了。若仅使用证书作为主要的认证手段,则在该请款下,k8s API无法撤销一个证书。
- 没有设置合理的令牌存活时间。
参考学习
- ⎈ RBAC least privileges misconfiguration | Kubernetes Goat (madhuakula.com)
- K06: Broken Authentication | OWASP Foundation
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黑名单
从上到下分别对应:Pod、Namespace、IP三个范畴。前两者可以通过Selector
来定义,IP则使用CIDR范围来标识。
在编写具体配置时,我们使用的是ingress
和egress
两个关键字,分别代表针对相对当前对象的流入和流出的流量的策略,且都是白名单,即只有这两类字段下类型的流量是允许的。
下面是k8s官方的一个例子及含义
1 | apiVersion: networking.k8s.io/v1 |
解决K07场景中存在的问题
下面我们写一个网络策略文件,禁止任何外部流量访问本地的redis服务:
1 | apiVersion: networking.k8s.io/v1 |
应用到网络中:
删除k07中的pod,自动重启后即可发现已经无法访问这个端口了,从而实现网络隔离的效果。
这里有一些可以参考使用的网路配置文件:ahmetb/kubernetes-network-policy-recipes: Example recipes for Kubernetes Network Policies that you can just copy paste (github.com)
参考学习
- K07: Network Segmentation | OWASP Foundation
- ⎈ Kubernetes namespaces bypass | Kubernetes Goat (madhuakula.com)
- ⎈ Secure Network Boundaries using NSP | Kubernetes Goat (madhuakula.com)
- Network Policies | Kubernetes
- 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_id
、aws_secret_access_key
以及k8s-goat-FLAG
。
利用
其实就是web里的git泄露嘛,直接上工具git-dumper,然后就可以使用git命令查看了:
可以看到有一个分支注释中写了添加变量的字样,切换过去看一下:
问题原因
emmmm,说白了就是打包程序的时候眼窝睁大点就好了。
参考学习
- ⎈ Sensitive keys in codebases | Kubernetes Goat (madhuakula.com)
- K08: Secrets Management | OWASP Foundation
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
对集群进行安全审计。
参考学习
- ⎈ KubeAudit - Audit Kubernetes clusters | Kubernetes Goat (madhuakula.com)
- K09: Misconfigured Cluster Components | OWASP Foundation
K10: Outdated and Vulnerable Kubernetes Components
定义
该场景因为利用的helm v2,现行的是v3。简单参考即可。
其实就是使用了带有漏洞的组件,如下图示意: