<p>O kubeadm pode registrar tokens de inicialização antes de tentar excluí-los</p>

Criado em 11 set. 2020  ·  3Comentários  ·  Fonte: kubernetes/kubeadm

Quais palavras-chave você pesquisou nos problemas do kubeadm antes de preencher este?

token , error

É um RELATÓRIO DE BUGS ou PEDIDO DE RECURSO?

_RELATÓRIO DE SEGURANÇA_

Resumo:

kubeadm comando delete recebe como entrada um ID de token de bootstrap ou um token completo. Antes de determinar se a entrada é apenas um id ou um token completo, kubeadm registra a entrada usando klog . Se a exclusão falhar, o token permanecerá válido. Um invasor com acesso aos logs pode usá-los para executar ações que exigem um token de bootstrap, como criar um cluster ou juntar nós a um cluster existente.

Versão do Kubernetes:

O código vulnerável está presente no kubernetes 1.19. A linha específica que contém a chamada para klog foi editada pela última vez em 24/03/2019.

Detalhes:

O código vulnerável está no repositório github.com/kubernetes , no arquivo kubernetes/cmd/kubeadm/app/cmd/token.go , na linha 423. Aqui está a função completa:

// RunDeleteTokens removes a bootstrap tokens from the server.
func RunDeleteTokens(out io.Writer, client clientset.Interface, tokenIDsOrTokens []string) error {
    for _, tokenIDOrToken := range tokenIDsOrTokens {
        // Assume this is a token id and try to parse it
        tokenID := tokenIDOrToken
        klog.V(1).Infof("[token] parsing token %q", tokenIDOrToken) // POTENTIAL LEAK HERE
        if !bootstraputil.IsValidBootstrapTokenID(tokenIDOrToken) {
            // Okay, the full token with both id and secret was probably passed. Parse it and extract the ID only
            bts, err := kubeadmapiv1beta2.NewBootstrapTokenString(tokenIDOrToken)
            if err != nil {
                return errors.Errorf("given token %q didn't match pattern %q or %q",
                    tokenIDOrToken, bootstrapapi.BootstrapTokenIDPattern, bootstrapapi.BootstrapTokenIDPattern)
            }
            tokenID = bts.ID
        }

        tokenSecretName := bootstraputil.BootstrapTokenSecretName(tokenID)
        klog.V(1).Infof("[token] deleting token %q", tokenID)
        if err := client.CoreV1().Secrets(metav1.NamespaceSystem).Delete(context.TODO(), tokenSecretName, metav1.DeleteOptions{}); err != nil {
            return errors.Wrapf(err, "failed to delete bootstrap token %q", tokenID)
        }
        fmt.Fprintf(out, "bootstrap token %q deleted\n", tokenID)
    }
    return nil
}

E aqui está a definição do comando kubeadm que chama essa função (no mesmo arquivo):

    deleteCmd := &cobra.Command{
        Use:                   "delete [token-value] ...",
        DisableFlagsInUseLine: true,
        Short:                 "Delete bootstrap tokens on the server",
        Long: dedent.Dedent(`
            This command will delete a list of bootstrap tokens for you.

            The [token-value] is the full Token of the form "[a-z0-9]{6}.[a-z0-9]{16}" or the
            Token ID of the form "[a-z0-9]{6}" to delete.
        `),
        RunE: func(tokenCmd *cobra.Command, args []string) error {
            if len(args) < 1 {
                return errors.Errorf("missing subcommand; 'token delete' is missing token of form %q", bootstrapapi.BootstrapTokenIDPattern)
            }
            kubeConfigFile = cmdutil.GetKubeConfigPath(kubeConfigFile)
            client, err := getClientset(kubeConfigFile, dryRun)
            if err != nil {
                return err
            }

            return RunDeleteTokens(out, client, args)
        },
    }

Impacto:

Um invasor que obtém um token de bootstrap dos logs pode usá-lo para autenticar com kubeadm e criar um novo cluster ou juntar nós a um cluster existente, por exemplo, para usar recursos de computação. Um invasor também pode executar outras ações usando kubeadm , por exemplo, listar ou excluir outros tokens.

Informações adicionais:

Eu relatei essa vulnerabilidade ao HackerOne e eles me informaram que, com base na alta complexidade do ataque e na baixa gravidade, eles acham que isso pode ser relatado e corrigido publicamente.

Abri um PR sobre kubernetes implementando uma correção: https://github.com/kubernetes/kubernetes/pull/94727

aresecurity kincleanup prioritbacklog

Todos 3 comentários

O comando delete do kubeadm leva como entrada um ID de token de bootstrap ou um token completo. Antes de determinar se a entrada é apenas um id ou um token completo, o kubeadm registra a entrada usando klog. Se a exclusão falhar, o token permanecerá válido. Um invasor com acesso aos logs pode usá-los para executar ações que exigem um token de bootstrap, como criar um cluster ou juntar nós a um cluster existente.

oi e obrigado por registrar o problema. para ser capaz de ler tais logs, seria necessário ter os privilégios corretos e eu presumiria que os logs estariam sob acesso root ou fornecidos a um grupo específico que já tem acesso mais alto do que os tokens de bootstrap.

tb:

  • --v=>1 deve ser habilitado durante a execução de kubeadm token delete se o token estiver em um formato válido
  • os tokens expiram após 24 horas por padrão

Acho que a melhoria no PR está quase tudo bem, mas não acho que devemos fazer backport para versões mais antigas (<1.20) devido à complexidade de tal ataque.

Eu concordo com @ neolit123 em não
WRT para a correção, eu sou +1 para remover o TokenID dos registros

fechando como https://github.com/kubernetes/kubernetes/pull/94727 mesclado.
obrigado

Esta página foi útil?
0 / 5 - 0 avaliações