|
| 1 | +--- |
| 2 | +title: Kubernetes API Server Bypass Risks |
| 3 | +description: > |
| 4 | + Security architecture information relating to the API server and other components |
| 5 | +content_type: concept |
| 6 | +--- |
| 7 | + |
| 8 | +<!-- overview --> |
| 9 | + |
| 10 | +The Kubernetes API server is the main point of entry to a cluster for external parties |
| 11 | +(users and services) interacting with it. |
| 12 | + |
| 13 | +As part of this role, the API server has several key built-in security controls, such as |
| 14 | +audit logging and {{< glossary_tooltip text="admission controllers" term_id="admission-controller" >}}. However, there are ways to modify the configuration |
| 15 | +or content of the cluster that bypass these controls. |
| 16 | + |
| 17 | +This page describes the ways in which the security controls built into the |
| 18 | +Kubernetes API server can be bypassed, so that cluster operators |
| 19 | +and security architects can ensure that these bypasses are appropriately restricted. |
| 20 | + |
| 21 | +<!-- body --> |
| 22 | + |
| 23 | +## Static Pods {#static-pods} |
| 24 | + |
| 25 | +The {{< glossary_tooltip text="kubelet" term_id="kubelet" >}} on each node loads and |
| 26 | +directly manages any manifests that are stored in a named directory or fetched from |
| 27 | +a specific URL as [*static Pods*](/docs/tasks/configure-pod-container/static-pod) in |
| 28 | +your cluster. The API server doesn't manage these static Pods. An attacker with write |
| 29 | +access to this location could modify the configuration of static pods loaded from that |
| 30 | +source, or could introduce new static Pods. |
| 31 | + |
| 32 | +Static Pods are restricted from accessing other objects in the Kubernetes API . For example, |
| 33 | +you can't configure a static Pod to mount a Secret from the cluster. However, these Pods can |
| 34 | +take other security sensitive actions, such as using `hostPath` mounts from the underlying |
| 35 | +node. |
| 36 | + |
| 37 | +By default, the kubelet creates a {{< glossary_tooltip text="mirror pod" term_id="mirror-pod">}} |
| 38 | +so that the static Pods are visible in the Kubernetes API. However, if the attacker uses an invalid |
| 39 | +namespace name when creating the Pod, it will not be visible in the Kubernetes API and can only |
| 40 | +be discovered by tooling that has access to the affected host(s). |
| 41 | + |
| 42 | +If a static Pod fails admission control, the kubelet won't register the Pod with the |
| 43 | +API server. However, the Pod still runs on the node. For more information, refer to |
| 44 | +[kubeadm issue #1541](https://github.com/kubernetes/kubeadm/issues/1541#issuecomment-487331701)). |
| 45 | + |
| 46 | +### Mitigations {#static-pods-mitigations} |
| 47 | + |
| 48 | +- Only [enable the kubelet static Pod manifest functionality](/docs/tasks/configure-pod-container/static-pod/#static-pod-creation) |
| 49 | + if required by the node. |
| 50 | +- If a node uses the static Pod functionality, restrict filesystem access to the static Pod manifest directory |
| 51 | + or URL to users who need the access. |
| 52 | +- Restrict access to kubelet configuration parameters and files to prevent an attacker setting |
| 53 | + a static Pod path or URL. |
| 54 | +- Regularly audit and centrally report all access to directories or web storage locations that host |
| 55 | + static Pod manifests and kubelet configuration files. |
| 56 | + |
| 57 | +## The kubelet API {#kubelet-api} |
| 58 | + |
| 59 | +The kubelet provides an HTTP API that is typically exposed on TCP port 10250 on cluster |
| 60 | +worker nodes. The API might also be exposed on control plane nodes depending on the Kubernetes |
| 61 | +distribution in use. Direct access to the API allows for disclosure of information about |
| 62 | +the pods running on a node, the logs from those pods, and execution of commands in |
| 63 | +every container running on the node. |
| 64 | + |
| 65 | +When Kubernetes cluster users have RBAC access to `Node` object sub-resources, that access |
| 66 | +serves as authorization to interact with the kubelet API. The exact access depends on |
| 67 | +which sub-resource access has been granted, as detailed in [kubelet authorization](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/#kubelet-authorization). |
| 68 | + |
| 69 | +Direct access to the kubelet API is not subject to admission control and is not logged |
| 70 | +by Kubernetes audit logging. An attacker with direct access to this API may be able to |
| 71 | +bypass controls that detect or prevent certain actions. |
| 72 | + |
| 73 | +The kubelet API can be configured to authenticate requests in a number of ways. |
| 74 | +By default, the kubelet configuration allows anonymous access. Most Kubernetes providers |
| 75 | +change the default to use webhook and certificate authentication. This lets the control plane |
| 76 | +ensure that the caller is authorized to access the `nodes` API resource or sub-resources. |
| 77 | +The default anonymous access doesn't make this assertion with the control plane. |
| 78 | + |
| 79 | +### Mitigations |
| 80 | + |
| 81 | +- Restrict access to sub-resources of the `nodes` API object using mechanisms such as |
| 82 | + [RBAC](/docs/reference/access-authn-authz/rbac/). Only grant this access when required, |
| 83 | + such as by monitoring services. |
| 84 | +- Restrict access to the kubelet port. Only allow specified and trusted IP address |
| 85 | + ranges to access the port. |
| 86 | +- [Ensure that kubelet authentication is set to webhook or certificate mode](/docs/reference/access-authn-authz/kubelet-authn-authz/#kubelet-authentication). |
| 87 | +- Ensure that the unauthenticated "read-only" Kubelet port is not enabled on the cluster. |
| 88 | + |
| 89 | +## The etcd API |
| 90 | + |
| 91 | +Kubernetes clusters use etcd as a datastore. The `etcd` service listens on TCP port 2379. |
| 92 | +the only clients that need access are the Kubernetes API server and any backup tooling |
| 93 | +that you use. Direct access to this API allows for disclosure or modification of any |
| 94 | +data held in the cluster. |
| 95 | + |
| 96 | +Access to the etcd API is typically managed by client certificate authentication. |
| 97 | +Any certificate issued by a certificate authority that etcd trusts allows full access |
| 98 | +to the data stored inside etcd. |
| 99 | + |
| 100 | +Direct access to etcd is not subject to Kubernetes admission control and is not logged |
| 101 | +by Kubernetes audit logging. An attacker who has read access to the API server's |
| 102 | +etcd client certificate private key (or can create a new trusted client certificate) can gain |
| 103 | +cluster admin rights by accessing cluster secrets or modifying access rules. Even without |
| 104 | +elevating their Kubernetes RBAC privileges, an attacker who can modify etcd can retrieve any API object |
| 105 | +or create new workloads inside the cluster. |
| 106 | + |
| 107 | +Many Kubernetes providers configure |
| 108 | +etcd to use mutual TLS (both client and server verify each other's certificate for authentication). |
| 109 | +There is no widely accepted implementation of authorization for the etcd API, although |
| 110 | +the feature exists. Since there is no authorization model, any certificate |
| 111 | +with client access to etcd can be used to gain full access to etcd. Typically, etcd client certificates |
| 112 | +that are only used for health checking can also grant full read and write access. |
| 113 | + |
| 114 | +### Mitigations {#etcd-api-mitigations} |
| 115 | + |
| 116 | +- Ensure that the certificate authority trusted by etcd is used only for the purposes of |
| 117 | + authentication to that service. |
| 118 | +- Control access to the private key for the etcd server certificate, and to the API server's |
| 119 | + client certificate and key. |
| 120 | +- Consider restricting access to the the etcd port at a network level, to only allow access |
| 121 | + from specified and trusted IP address ranges. |
| 122 | + |
| 123 | + |
| 124 | +## Container runtime socket {#runtime-socket} |
| 125 | + |
| 126 | +On each node in a Kubernetes cluster, access to interact with containers is controlled |
| 127 | +by the container runtime (or runtimes, if you have configured more than one). Typically, |
| 128 | +the container runtime exposes a Unix socket that the kubelet can access. An attacker with |
| 129 | +access to this socket can launch new containers or interact with running containers. |
| 130 | + |
| 131 | +At the cluster level, the impact of this access depends on whether the containers that |
| 132 | +run on the compromised node have access to Secrets or other confidential |
| 133 | +data that an attacker could use to escalate privileges to other worker nodes or to |
| 134 | +control plane components. |
| 135 | + |
| 136 | +### Mitigations {#runtime-socket-mitigations} |
| 137 | + |
| 138 | +- Ensure that you tightly control filesystem access to container runtime sockets. |
| 139 | + When possible, restrict this access to the `root` user. |
| 140 | +- Isolate the kubelet from other components running on the node, using |
| 141 | + mechanisms such as Linux kernel namespaces. |
| 142 | +- Ensure that you restrict or forbid the use of [`hostPath` mounts](/docs/concepts/storage/volumes/#hostpath) |
| 143 | + that include the container runtime socket, either directly or by mounting a parent |
| 144 | + directory. Also `hostPath` mounts must be set as read-only to mitigate risks |
| 145 | + of attackers bypassing directory restrictions. |
| 146 | +- Restrict user access to nodes, and especially restrict superuser access to nodes. |
0 commit comments