The Kubernetes community discovered CVE-2021-25740, a vulnerability that can be exploited by attackers to launch confused deputy attacks to access cluster services that they would otherwise be unable to access. This topic describes the impacts of the vulnerability, and how to detect and mitigate the vulnerability.

CVE-2021-25740 is rated as low severity and its Common Vulnerability Scoring System (CVSS) score is 3.0.

Affected versions

All Kubernetes versions. For more information about the vulnerability, see #103675.

Impacts

If an attacker has permissions to create or modify Endpoints or EndpointSlices, the attacker can call the Kubernetes API to modify the addresses of Endpoints. In this case, the attacker may use a LoadBalancer or Ingress to access backend IP addresses that the attacker is not supposed to access. Besides, if the network policy of the cluster already trusts the LoadBalancer or Ingress, the network policy cannot be used to prevent exposure from other namespaces.

Detection

Services for which no selectors are specified rely on custom Endpoints and are vulnerable to the preceding attack. We recommend that you run the following command to check all Services and their selectors in the cluster:

kubectl get svc --all-namespaces -o=custom-columns='NAME:metadata.name,NAMESPACE:metadata.namespace,SELECTOR:spec.selector'
Note If no selectors are specified for the default/kubernetes Service, the Endpoints of the Service are managed by the Kubernetes API Server. This is normal.

Mitigation

No patch is available for this vulnerability. It can be mitigated only by restricting access to the vulnerable features. To mitigate the exposure, we recommend that you run the following commands to update the system:aggregate-to-edit role and restrict write access to Endpoints and EndpointSlices. This revokes write access to Endpoints from the admin and edit roles.

# Allow kubectl auth reconcile to work
kubectl annotate --overwrite clusterrole/system:aggregate-to-edit rbac.authorization.kubernetes.io/autoupdate=true

# Test reconcile, then run for real if happy
kubectl auth reconcile --remove-extra-permissions -f aggregate_to_edit_no_endpoints.yaml.txt --dry-run
kubectl auth reconcile --remove-extra-permissions -f aggregate_to_edit_no_endpoints.yaml.txt

# Prevent autoreconciliation back to old state
kubectl annotate --overwrite clusterrole/system:aggregate-to-edit rbac.authorization.kubernetes.io/autoupdate=false

The following code block shows the content of the aggregate_to_edit_no_endpoints.yaml.txt file that is used in the preceding commands:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: null
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
  name: system:aggregate-to-edit
rules:
- apiGroups:
  - ""
  resources:
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  - secrets
  - services/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - impersonate
- apiGroups:
  - ""
  resources:
  - pods
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  - persistentvolumeclaims
  - replicationcontrollers
  - replicationcontrollers/scale
  - secrets
  - serviceaccounts
  - services
  - services/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - apps
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - replicasets
  - replicasets/scale
  - statefulsets
  - statefulsets/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - ingresses
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - networkpolicies
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update

After you complete the preceding operations, new versions of Kubernetes cannot modify the default permissions of the system:aggregate-to-edit role. No new default permissions are added to this role in Kubernetes V1.14.0 and later versions. We recommend that you remove the autoupdate=false annotation immediately after Kubernetes provides a fix to this vulnerability.

If you require the permissions to modify Endpoints and EndpointSlices for certain use cases, we recommend that you create a new role with the desired permissions and use the role only for these cases.

Similar attacks can be launched by using Ingresses that can forward traffic to ExternalName Services. In this case, an attacker can forward network traffic to Services in other namespaces or sensitive Endpoints. If you are using the Ingress API, we recommend that you check whether your Ingress can forward traffic to ExternalName Services. If your Ingress cannot forward traffic to ExternalName Services, you are not affected by this attack. If your Ingress can forward traffic to ExternalName Services, you must temporarily disable the functionality.