<p>kubeadm puede registrar tokens de arranque antes de intentar eliminarlos</p>

Creado en 11 sept. 2020  ·  3Comentarios  ·  Fuente: kubernetes/kubeadm

¿Qué palabras clave buscó en los problemas de kubeadm antes de presentar esta?

token , error

¿Es este un INFORME DE ERROR o una SOLICITUD DE FUNCIÓN?

_REPORTE DE SEGURIDAD

Resumen:

kubeadm comando delete toma como entrada un ID de token de arranque o un token completo. Antes de determinar si la entrada es solo una identificación o un token completo, kubeadm registra la entrada usando klog . Si la eliminación falla, el token seguirá siendo válido. Un atacante que tenga acceso a los registros podría usarlo para realizar acciones que requieran un token de arranque, como crear un clúster o unir nodos a un clúster existente.

Versión de Kubernetes:

El código vulnerable está presente en kubernetes 1.19. La línea específica que contiene la llamada a klog se editó por última vez el 2019-03-24.

Detalles:

El código vulnerable está en el repositorio github.com/kubernetes , en el archivo kubernetes/cmd/kubeadm/app/cmd/token.go , en la línea 423. Aquí está la función 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
}

Y aquí está la definición del comando kubeadm que llama a esa función (en el mismo archivo):

    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:

Un atacante que obtenga un token de arranque de los registros podría usarlo para autenticarse con kubeadm y crear un nuevo clúster o unir nodos a un clúster existente, por ejemplo, para utilizar recursos informáticos. Un atacante también podría realizar otras acciones usando kubeadm , por ejemplo, enumerar o eliminar otros tokens.

Información adicional:

He informado de esta vulnerabilidad a HackerOne y me han informado que, en base a la alta complejidad del ataque y la baja gravedad, creen que esto se puede informar y solucionar públicamente.

Abrí un PR en kubernetes implementando una solución: https://github.com/kubernetes/kubernetes/pull/94727

aresecurity kincleanup prioritbacklog

Todos 3 comentarios

El comando de eliminación de kubeadm toma como entrada un ID de token de arranque o un token completo. Antes de determinar si la entrada es solo una identificación o un token completo, kubeadm registra la entrada usando klog. Si la eliminación falla, el token seguirá siendo válido. Un atacante que tenga acceso a los registros podría usarlo para realizar acciones que requieran un token de arranque, como crear un clúster o unir nodos a un clúster existente.

hola, y gracias por registrar el problema. para poder leer tales registros, uno necesitaría tener los privilegios correctos y supongo que los registros estarían bajo acceso de root o entregados a un grupo específico que ya tiene un acceso más alto que los tokens de arranque.

además:

  • --v=>1 debe habilitarse durante la ejecución de kubeadm token delete si el token está en formato válido
  • los tokens caducan después de 24 horas de forma predeterminada

Creo que la mejora en las relaciones públicas es mayormente buena, pero no creo que debamos retroceder a versiones anteriores (<1.20) debido a la complejidad de tal ataque.

Estoy de acuerdo con @ neolit123 en no hacer backport (a menos que haya necesidades realmente específicas)
WRT a la solución, soy +1 para eliminar el TokenID de los registros

cerrando como https://github.com/kubernetes/kubernetes/pull/94727 fusionado.
Gracias

¿Fue útil esta página
0 / 5 - 0 calificaciones