Americas

Asia

Oceania

lconstantin
CSO Senior Writer

New Kubernetes vulnerability allows privilege escalation in Windows

News Analysis
13 Mar 20246 mins
Application SecurityDevSecOpsVulnerabilities

Attackers can abuse YAML configuration files to execute malicious commands in Windows hosts.

Editor’s note: This article, originally published on September 13, 2023, has been updated with new research on a similar vulnerability.

The latest version of Kubernetes released last month includes patches for an entire class of vulnerabilities that allow attackers to abuse the subPath property of YAML configuration files to execute malicious commands on Windows hosts. “The vulnerability allows remote code execution with SYSTEM privileges on all Windows endpoints within a Kubernetes cluster,” Akamai researcher Tomer Peled said about the vulnerability he found and which triggered the discovery of two other similar issues. “To exploit this vulnerability, the attacker needs to apply a malicious YAML file on the cluster.”

Attack YAML

Kubernetes is a widely popular container orchestration system that’s used by organizations to automate the deployment and management of applications running in containers. YAML is a language used to write configuration and other management files for Kubernetes. It therefore makes sense for it to be a target for potential attackers as it’s a direct way to push user input to the Kubernetes engine and have it parsed and interpreted.

YAML parsing issues have led to Kubernetes vulnerabilities before. For example the CVE-2022-1471 remote code execution vulnerability in the SnakeYaml parser impacted the Kubernetes Java client, while the CVE-2021-25749 flaw allowed misspelled user names to be included in a YAML file resulting in the execution of workloads as root. The CVE-2017-1002101 and CVE-2021-25741 issues then showed how the subPath subproperty in a YAML file can be used in combination with symbolic links (symlinks) to access files outside the container, breaking the isolation. It was these last two flaws that gave Peled the idea to investigate the issue further.

Kubernetes allows mounting a directory from the host system inside a container through a property called volume. This is a widely used feature and comes with several subproperties to define the path of the directory on the host and the mount path inside the container. The mountPath further has a subPath property that when provided in a YAML file is processed by kubelet, a core Kubernetes service.

New path processing issues allows PowerShell code execution

Peled found that when the subPath string is processed, kubelet also checks if it is a symlink, which is part of the defenses put in place for the older vulnerabilities. However, it does this through a PowerShell command that is invoked by the “exec.Command” function call. This opens the possibility that an attacker could attach PowerShell code to the subPath string where it would be executed.

“PowerShell allows users to evaluate values inside strings before they are used,” the researcher explained. “This can be done by adding $(<experssion_to_be_evaluated>) to your string […]. Any PowerShell command can be inserted between the parentheses and will be evaluated — such as $(Start-Process cmd), $(Invoke-Expression exp), and other PowerShell treats.”

So, for example, if an attacker supplies a YAML file to a Kubernetes node that runs on Windows with a subPath that includes $(Start-Process cmd), this will be sent to PowerShell by kubelet during the process of path validation and will be executed with the Windows privileges of the kubelet service — SYSTEM.

This vulnerability is now tracked as CVE-2023-3676 and was patched in Kubernetes 1.28, but it also led to the discovery and fixing of two more similar command injection vulnerabilities: CVE-2023-3955 and CVE-2023-3893. The flaw impacts Kubernetes on Windows in its default configuration, but the attacker needs to obtain apply privileges to a node.

How to mitigate the YAML-enabled Kubernetes vulnerability

“The Kubernetes team chose to patch this class of vulnerabilities by passing parameters from environment variables instead of from user input,” Peled said. “By passing down the values in this manner, the parameters are treated as strings — therefore, they will not be evaluated as expressions by PowerShell.”

If they can’t update to the patched version immediately, admins can disable the use of Volume.Subpath, but this will also cripple a commonly used feature and functionality. Another option is to use the Open Policy Agent (OPA), an open-source agent that can take policy-based actions based on the received data. Admins can create rules to block certain YAML files from being implemented using the Rego language in OPA, and Akamai provides an example for such a blocking rule in its blog post.

Peled also recommends using role-based access control (RBAC) to limit the number of users who can perform actions on a cluster.

Update: Command injection via Kubernetes local volumes

Another vulnerability found by Peled is tracked as CVE-2023-5528 and was patched in Kubernetes versions 1.28.4, 1.27.8, 1.26.11, and 1.25.16 released in November 2023. The flaw is similar to CVE-2023-3676 and impacts Kubernetes on Windows in default configuration, but instead of targeting the subPath volume feature it stems from the local volumes feature.

Local volumes are a type of volumes supported in Kubernetes that allows users to mount disk partitions inside a pod, compared to hostPath volumes that allow users to mount specific directories. A cluster admin can provision storage space ahead of time by creating a persistentVolume and then users can use YAML when configuring a pod to make a persistentVolumeClaim in order to claim some of that storage space.

The problem is that when parsing such requests from a YAML file the kubelet service used to rely on a function that used exec.command to execute a command on the system in order to create a symlink between the volume and the location inside the pod. The Windows command line terminal accepts command concatenation — executing multiple commands in a single line — by placing the && characters between commands.

Peled figured out that an attacker could place commands in the Path definition of the persistentVolumeClaim in the YAML and surround them with the && characters and these would be executed on the host system when the claim is processed by the kubelet service which runs with SYSTEM privileges. The Kubernetes team fixed the command injection vulnerability by replacing the cmd call made by the kubelet service with a function in GO called “os.Symlink()” that will perform the same operation of creating symlinks but in a safe manner.