Precisa de computação em nuvem? Comece agora mesmo

Que Cluster: Vulnerabilidade em Volumes Locais no Kubernetes

Tomer Peled

escrito por

Tomer Peled

March 13, 2024

Tomer Peled

escrito por

Tomer Peled

Tomer Peled é pesquisador de segurança da Akamai. Em seu trabalho diário, ele realiza pesquisas que vão de pesquisas de vulnerabilidade a questões internas do sistema operacional. Em seu tempo livre, ele gosta de cozinhar, de Krav Magá e jogar em seu computador.

Estar ciente da falta de limpeza de entrada no código-fonte do Kubernetes significa que você pode tomar precauções externas para ajudar a evitar um impacto grave na segurança.
Estar ciente da falta de limpeza de entrada no código-fonte do Kubernetes significa que você pode tomar precauções externas para ajudar a evitar um impacto grave na segurança.

Comentários editoriais e adicionais por Tricia Howard

Resumo executivo

  • A vulnerabilidade permite a execução remota de código com privilégios de SYSTEM em todos os pontos de extremidade do Windows em um cluster do Kubernetes. Para explorar essa vulnerabilidade, o invasor precisa aplicar arquivos YAML mal-intencionados no cluster.

  • Essa vulnerabilidade pode levar à apropriação total de todos os nós do Windows em um cluster.

  • Essa vulnerabilidade pode ser explorada em instalações padrão do Kubernetes (anterior à versão 1.28.4) e foi testada em implantações locais e no Azure Kubernetes Service.

  • Nesta publicação do blog, fornecemos um arquivo YAML de prova de conceito, bem como uma regra OPA (Open Policy Agent) para bloquear essa vulnerabilidade.

Introdução

Kubernetes e contêineres em geral se tornaram uma força predominante no mundo da segurança e, como tal, têm sido um ponto de interesse para pesquisadores em todo o mundo (incluindo nós). Nossa jornada de pesquisa nos levou inicialmente ao CVE-2023-3676 (CVSS de 8,8): uma vulnerabilidade de injeção de comando que pode ser explorada pela aplicação de um arquivo YAML mal-intencionado no cluster. Como a estrutura Kubernetes usa arquivos YAML para basicamente tudo, desde a configuração da interface de rede do contêiner até o gerenciamento de pods e até mesmo manipulação de segredos, uma exploração dessa vulnerabilidade pode ter consequências desastrosas.

A descoberta dessa vulnerabilidade levou à descoberta de duas outras que compartilham a mesma causa raiz: chamada de função insegura e falta de limpeza de entrada do usuário. 

A falta de limpeza do parâmetro subPath em arquivos YAML que cria pods com volumes abre uma oportunidade para uma injeção mal-intencionada. Essa foi a descoberta original, mas na extremidade final dessa pesquisa, notamos um possível lugar no código que parecia que poderia levar a outra vulnerabilidade de injeção de comando. Depois de várias tentativas, conseguimos alcançar um resultado semelhante: executar comandos como o serviço "kubelet" (privilégios de SYSTEM). É aqui que começaremos nossa jornada hoje com o CVE-2023-5528.

Nesta publicação do blog, veremos os detalhes da vulnerabilidade e os problemas no código-fonte do Kubernetes que permitem isso, e também analisaremos o patch da equipe do Kubernetes e sua eficácia. Embora a aplicação de patches o mais rápido possível seja recomendada, incluímos guias curtos sobre como procurar os nós afetados e como aplicar uma regra do OPA (Open Policy Agent) para ajudar a detectar e bloquear esse tipo de comportamento.

Esta publicação destaca mais uma vez como é crucial verificar os YAMLs de configuração do Kubernetes, já que a limpeza de entradas não existe em várias áreas de código no próprio Kubernetes e em seus projetos auxiliares (como entrada, por exemplo).

Detalhes da vulnerabilidade

Antes de entrar nas especificidades dessa vulnerabilidade em si, devemos primeiro entender alguns componentes-chave no Kubernetes.

O que são volumes do Kubernetes?

Volumes Kubernetes são um recurso destinado a suportar o compartilhamento de dados entre pods ou armazená-los persistentemente fora do ciclo de vida de um pod. Há muitos tipos de volume diferentes que os desenvolvedores podem usar. Por exemplo, em nossa pesquisa anterior sobre o CVE-2023-3676, usamos volumes hostPath . Para essa vulnerabilidade, estamos nos concentrando em volumes locais, outro tipo de volume do Kubernetes. Os volumes locais são projetados para permitir que os usuários montem partições de disco dentro de um pod, enquanto os volumes do hostPath são projetados para permitir que os usuários montem diretórios de seu nó (host) em um pod.

Ao criar um pod que inclua um volume local, o serviço kubelet atingirá (eventualmente) a função "MountSensitive()". Dentro dela, há uma chamada de linha cmd para "exec.command", que cria um link simbólico entre o local do volume no nó e o local dentro do pod (Figura 1).

Ao criar um pod que inclui um volume local, o serviço do kubelet alcançará (eventualmente) a função "MountSensitive()". Dentro dela, há uma chamada de linha cmd para "exec.command", que faz um link simbólico entre o local do volume no nó e o local dentro do pod (Figura 1). Fig. 1: Linha cmd vulnerável

Muitos terminais usam alguma versão da concatenação de comandos (Figura 2) em suas operações para facilitar o uso. Esse também é o caso da Solicitação de comando do Windows (cmd) : usando o token "&&", o terminal executará dois ou mais comandos, um após o outro.

  C:\Users\user>echo "by using &&" && echo "we can execute multiple commands in the same command line"
  "by using &&"
  "we can execute multiple commands in the same command line"

  C:\Users\user>

Fig. 2: Concatenação de comandos no cmd

O fato de possamos controlar um dos parâmetros na execução cmd significa que podemos usar injeção de comando. No entanto, há alguns pré-requisitos para isso:  para os usuários usarem volumes locais, eles precisam especificar ou criar um persistentVolume.

O que são persistentVolumes?

persistentVolumes são recursos de armazenamento que um administrador de cluster pode criar para provisionar espaço de armazenamento antes do tempo que durará além da vida útil do pod (Figura 3). Quando um persistentVolume é criado, um usuário pode solicitar espaço de armazenamento usando uma persistentVolumeClaim.

persistentVolumes são recursos de armazenamento que um administrador de cluster pode criar para provisionar espaço de armazenamento antes do tempo que durará além da vida útil do pod (Figura 3). Fig. 3: Um exemplo de persistentVolume

É aqui que a injeção pode ser colocada. Um invasor pode alterar o valor do parâmetro "local.path" dentro do arquivo YAML persistentVolume para adicionar um comando mal-intencionado que será executado durante o processo de montagem.

Na Figura 4, usamos o "&calc.exe&&" benigno (que abre uma calculadora no nó), mas esse processo pode ser usado para um resultado muito mais mal-intencionado.

Na Figura 4, usamos o "&calc.exe&&" benigno (que abre uma calculadora no nó), mas esse processo pode ser usado para um resultado muito mais mal-intencionado. Fig. 4: persistentVolume com nosso comando "mal-intencionado"

A Figura 5 mostra como uma exploração bem-sucedida se parecerá com um nó de destino após a injeção de nosso comando "mal-intencionado" da calculadora.

A Figura 5 mostra como uma exploração bem-sucedida se parecerá com um nó de destino após a injeção de nosso comando "mal-intencionado" da calculadora. Fig. 5: Prova de conceito do ataque

Análise de patches

Em um esforço para remover a oportunidade de injeção, a equipe do Kubernetes optou por excluir a chamada cmd  e substituí-la por uma função GO nativa que executará a mesma operação "os.Symlink()" (Figura 6).

Em um esforço para remover a oportunidade de injeção, a equipe do Kubernetes optou por excluir a chamada cmd e substituí-la por uma função GO nativa que executará a mesma operação "os.Symlink()" (Figura 6). Fig. 6: Como a função cuida do patch

Agora, a biblioteca GO "os" só executará uma operação symlink, como foi inicialmente previsto.

Será que estou vulnerável?

 Para que os usuários sejam afetados por essa vulnerabilidade, o Kubernetes deve ser uma  versão anterior à 1.28.4. Se ainda não tiver corrigido, é uma boa ideia dar prioridade a esta vulnerabilidade. Isso é ainda mais importante para organizações com nós do Windows dentro de um cluster, pois é onde a vulnerabilidade está.

Felizmente, não parece ser o padrão do setor. Um administrador pode testar facilmente se o cluster da organização contém nós do Windows executando o comando mostrado na Figura 7 no controlador de cluster.

  root@controller:~/$ kubectl get nodes -o wide --show-labels | grep “os=windows”

  akswin000000                        Ready    agent   4d17h   v1.26.6   agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows…
  akswin000001                        Ready    agent   4d17h   v1.26.6   agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows…
  root@controller:~/$

Fig. 7: O comando que mostra os nós do Windows em um cluster

É fácil determinar se você está vulnerável. Observe a parte "os=windows". Se não houver nós do Windows, o comando não teria nenhuma saída, o que significa que você não está vulnerável.

Mitigação

A única mitigação disponível é corrigir o Kubernetes para uma versão posterior à 1.28.3.

Dito isso, sabemos que a aplicação imediata de patches não é algo que pode ser feito em algumas organizações e redes. Para ajudar a acomodar o risco de não aplicar patches, fornecemos uma regra OPA para ajudar a detectar e bloquear esse tipo de comportamento. 

  package kubernetes.admission

  deny[msg] {                                                                 
    input.request.kind.kind == "PersistentVolume"
    path := input.request.object.spec.local.path                 
    contains(path, "&")                                     
    msg := sprintf("malicious path: %v was found", [path])     
}

OPA é um agente de código aberto que permite que os usuários recebam dados sobre o tráfego que entra e sai dos nós e tomem ações baseadas em políticas sobre os dados recebidos.

Lembre-se de que essa vulnerabilidade afeta apenas os nós do Windows. Se o seu cluster do Kubernetes não tiver nós do Windows, você não precisa se apressar para corrigir essa vulnerabilidade específica. Mas é importante corrigi-la de qualquer forma quando tiver tempo.

Como o problema está no código-fonte, essa ameaça permanecerá ativa, e a exploração dela provavelmente aumentará. É por isso que recomendamos a aplicação de patches em seu cluster, mesmo que ele não tenha nós do Windows.

Conclusão

Essa vulnerabilidade é um ótimo exemplo do motivo pelo qual o modelo de responsabilidade compartilhada é crucial em termos de segurança. Estar ciente da falta de limpeza de entrada no código-fonte do Kubernetes significa que você pode tomar precauções externas para ajudar a evitar um impacto grave na segurança. 

Sete vulnerabilidades diferentes de injeção de comando foram descobertas apenas em 2023, com mais oportunidades em outras áreas do código. As equipes da Blue e suas organizações devem estar mais alertas para essa tendência crescente e tentar monitorar o conteúdo dos arquivos YAML, pois eles podem conter ameaças ocultas. A regra OPA que fornecemos neste post pode ajudar com esse esforço.

O Akamai Security Intelligence Group continuará monitorando esta ameaça e outras semelhantes e publicará nossas descobertas. Para acompanhar essa vulnerabilidade e outras pesquisas de segurança, siga-nos no X (ex-Twitter).

Queremos agradecer à equipe do Kubernetes por sua resposta muito rápida e boa comunicação.

Cronograma de divulgação

  • 01/11/2023 – Vulnerabilidade divulgada à equipe do Kubernetes

  • 11/11/2023 – CVEs atribuídos pela equipe do Kubernetes

  • 14/11/2023 – Kubernetes publicou correções de CVE 

  • 13/03/2024 – Esta postagem do blog publicada



Tomer Peled

escrito por

Tomer Peled

March 13, 2024

Tomer Peled

escrito por

Tomer Peled

Tomer Peled é pesquisador de segurança da Akamai. Em seu trabalho diário, ele realiza pesquisas que vão de pesquisas de vulnerabilidade a questões internas do sistema operacional. Em seu tempo livre, ele gosta de cozinhar, de Krav Magá e jogar em seu computador.