Etcd简介
Etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库, 用于服务发现、共享配置以及一致性保障等。目前已广泛应用在kubernetes、ROOK、CoreDNS、M3以及openstack等领域。
Etcd内部采用raft协议作为一致性算法,基于Go语言实现。从组成上来看,Etcd主要由四个部分组成:HTTP Server、Store、Raft以及WAL。我们可以通过Etcd架构图来更好的了解Etcd,Etcd架构图可见下图所示:
图-1 Etcd架构图
Etcd比较常见的版本有v2版本和v3版本,v2、v3版本的共同点是共享同一套raft协议代码,不同点是二者为两个独立的应用,互不兼容,其接口、存储都是不相同的。
值得注意的是,Kubernetes集群已经在Kubernetes v1.11中弃用Etcdv2 版本,在新版本的Kubernetes中,Kubernetes采用 Etcd v3存储数据。
Etcd与Kubernetes
在对Etcd有了初步了解之后,我们来看一下Kubernetes中Etcd的应用。
在Kubernetes集群中,存在有控制平面组件以及Node组件两大类组件,在这两类组件中包含了多种不同功能的组件,这些组件共同保证了Kubernetes集群的正常运行。Kubernetes集群组件结构可参照下图:
图- 2 Kubernetes集群组件
Etcd在Kubernetes中扮演着控制平面组件的角色,是兼具一致性和高可用性的键值数据库,在Kubernetes集群中扮演着保存 Kubernetes 所有集群数据的后台数据库的角色。
Kubernetes系统中一共有两个服务需要用到Etcd进行协同和与存储,分别是Kubernetes自身与网络插件 flannel。
在Kubernetes 集群的配置过程中,需要安装Etcd组件,Etcd的yaml文件可见下图:
图- 3 Etcd组件配置文件
从上文配置文件可见,Etcd在配置过程中需要配置两个url地址:listen-client-urls以及 listen-peer-urls,分别监听在2379端口以及2380端口。其中listen-peer-urls用于 etcd 集群同步信息并保持连接,而listen-client-urls则用于接收用户端发来的 HTTP请求。
Ectd常见风险
Etcd常见风险包括:
启动etcd时,未使用client-cert-auth参数打开证书校验;
Etcd 2379端口公网暴露;
由于SSRF漏洞导致Etcd 127.0.0.1:2379 可访问;
Etcd cert泄露。
我们分别来看一下以上四个风险点分别是如何对Etcd造成威胁的。
首先来看一下未使用client-cert-auth参数打开证书校验带来的风险:
在启动etcd时,正确的做法是使用client-cert-auth参数打开证书校验,见下图配置文件红框处:
图- 4 开启证书校验
在打开证书校验选项后,通过本地127.0.0.1:2379地址可以免认证访问Etcd服务,但通过其他地址访问要携带cert进行认证访问
在未使用client-cert-auth参数打开证书校验时,任意地址访问Etcd服务都不需要进行证书校验,此时Etcd服务存在未授权访问风险。
接下来,我们分析一下Etcd 2379端口公网暴露所带来的风险:
在配置Etcd时,正确的做法是为listen-client-urls参数配置一个合理的IP地址,Etcd将监听在给定端口和接口上,如下图红框处:
图- 5 配置listen-client-urls
由于错误的配置,将listen-client-urls IP配置为0.0.0.0,那么Etcd 将会在所有接口上监听给定端口,这将导致Etcd 2379端口在公网暴露。
接下来,我们分析一下由于SSRF漏洞导致Etcd 127.0.0.1:2379 可访问风险:
即使Etcd进行了正确的配置,由于服务器上应用程序的SSRF漏洞,导致Etcd 127.0.0.1:2379 可访,此接口默认不需要证书校验,因此攻击者可以通过SSRF漏洞访问此接口并读取Etcd中的敏感数据。
最后,我们来看一下Etcd cert泄露所带来的风险:
在配置安全通信后, 需要使用TLS 身份验证来完成Etcd服务的访问,通常使用如下的方式有效证书证书进行访问:
ETCDCTL_API=3 etcdctl --endpoints etcd_ip:2379 \ --cert=/etc/kubernetes/pki/etcd/client.crt \ --key=/etc/kubernetes/pki/etcd/client.key \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \
如果证书被窃取,攻击者可以使用获取到的证书访问Etcd服务。
Ectd攻击场景
在搭建Kubernetes并配置Etcd服务时,如果出现了上一章节中提到的错误配置或漏洞风险点,攻击者可以利用Etcd的风险点发起攻击。
我们在这里列举集中常见的攻击者攻击方式,通过以攻促防的方式,带领读者了解Etcd服务所面临的风险以及威胁。
在开始介绍攻击常见前,我们先来了解一款常见的etcd命令行工具——etcdctl。
etcdctl是一款命令行客户端,提供一些简洁的命令,用户无需使用HTTP API,可以直接使用etcdctl提供的指令与etcd服务进行交互。
可以通过如下地址进行下载:
https://github.com/coreos/etcd/releases
接下来我们对几种攻击场景逐一进行分析。
Etcd初始访问
Etcd 2379端口公网暴露
在这个场景中,攻击者可以利用暴露在公网上的2379端口访问Etcd服务。但在这个场景中,攻击者依然面临着两个不同的情况,即当前Etcd服务在启动时是否使用client-cert-auth参数开启证书校验。
如果当前Etcd服务未进行证书校验,则存在未授权访问漏洞,可以通过如下指令获取top-levelkeys数据
/etcdctl--endpoints=https://etcd_ip:2379/ get / --prefix --keys-only
具体操作可见下图:
图- 6 获取top-level keys数据
如果当前Etcd服务使用证书进行校验,则需要使用获取到的证书进行配置并访问
在使用etcdctl工具之前,需要配置如下三个环境变量:
ETCDCTL_CERT
ETCDCTL_CACERT
ETCDCTL_KEY
在配置了正确的证书后,即可通过etcdctl工具对Etcd服务进行访问。
由于SSRF漏洞导致Etcd localhost端口访问
在这个场景中,由于SSRF漏洞导致Etcd 127.0.0.1:2379可访问,而且Etcd 127.0.0.1:2379地址默认不需要进行证书校验,即可以直接访问,因此当Etcd服务器上应用程序存在SSRF漏洞时,攻击者可以通过构造内外请求的方式,向Etcd服务API接口发送恶意指令。
Etcd凭据窃取
通过初始访问阶段,攻击者获取了Etcd服务的访问权限,并可以使用etcdctl工具读取Etcd中存储的数据,接下来介绍一下在此阶段中应用的技术。
获取clusterrole key
可以使用如下指令读取存储于Etcd中的与clusterrole有关的key
etcdctl--endpoints=https://etcd_ip:2379/ get / --prefix --keys-only | grep/secrets/kube-system/clusterrole。
图- 7 读取clusterrole有关的key
获取token key值
可以通过如下指令,通过上一步中获取到的key,读取其中的值:
etcdctl--endpoints=https://etcd_ip:2379/ get / /xxx/secrets/kube-system/clusterrole-xxx
从返回的数据中,挑选出一个具有高权限的role并读取其token。toke数据通常以字符串”ey”开头,并截取到字符串
“#kubernetes.io/service-account-token”之前部分,见下图选中部分:
图表- 8 截取token数据
至此,我们已经获取了有效的Kube Apiserver 访问token。
Kube Apiserver命令执行
通过上一阶段窃取到的token认证访问Kube Apiserver,使用kubectl接管集群。具体操作如下:
kubectl--insecure-skip-tls-verify -s https://kube_apiserver:6443/--token="[ey...]" -n kube-system get nodes
图表- 9 使用kubectl接管集群
使用上下文简化kubectl操作
生成context
可以使用如下命令生成context:
图表- 10 生成context
配置context简化kubectl操作
Kubernetes通过上下文(context),使用简便的名称来对访问参数进行分组。每个上下文都有三个参数:cluster、namespace 和user。kubectl工具可以通过kubeconfig参数指定我们生成的上下文 context_config:
图表- 11 配置context
通过这个方式,即可简化kubectl操作,无需每次执行kubectl命令时填写TOKEN。
Etcd防御与加固
通过上文攻击场景介绍,我们提出如下的防护建议用以加固Etcd服务:
在启动Etcd时,使用client-cert-auth参数打开证书校验;
Etcd数据加密存储,确保Etcd数据泄露后无法利用;
正确的配置listen-client-urls参数,防止外网暴露;
尽量避免在Etcd所在的节点上部署Web应用程序,以防通过Web应用漏洞攻击Etcd localhost地址。
写在最后
Etcd组件在Kubernetes中充当着保存集群数据的后台数据库这一重要角色,因此Etcd组件安全对集群来说也是尤为重要。通过上文分析可见,虽然Etcd组件提供了较为安全的鉴权功能,以保证数据的安全性,但是由于用户在配置使用Etcd组件时安全意识不足或配置错误,将会导致集群数据被非法访问或篡改。Ectd数据泄露,将会为集群带来严重的安全问题。未来我们将持续关注Etcd组件安全问题。
参考链接
https://yeasy.gitbook.io/docker_practice/etcd/etcdctl
https://kubernetes.io/zh/docs/concepts/overview/components/
https://www.huweihuang.com/kubernetes-notes/etcd/etcdctl-v3.html
https://www.cdxy.me/?p=827
https://tttang.com/archive/1465/
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课