<p>kubeadm kann Bootstrap-Token protokollieren, bevor versucht wird, sie zu löschen</p>

Erstellt am 11. Sept. 2020  ·  3Kommentare  ·  Quelle: kubernetes/kubeadm

Nach welchen Schlüsselwörtern haben Sie in kubeadm-Problemen gesucht, bevor Sie dieses eingereicht haben?

token , error

Ist dies ein FEHLERBERICHT oder eine FEATURE-ANFRAGE?

_SICHERHEITSBERICHT

Zusammenfassung:

kubeadm Befehl delete nimmt als Eingabe entweder eine Bootstrap-Token-ID oder einen vollständigen Token. Bevor bestimmt wird, ob die Eingabe nur eine ID oder ein vollständiges Token ist, protokolliert kubeadm die Eingabe mit klog . Wenn das Löschen fehlschlägt, bleibt das Token gültig. Ein Angreifer, der Zugriff auf die Protokolle hat, könnte damit Aktionen ausführen, die ein Bootstrap-Token erfordern, z. B. das Erstellen eines Clusters oder das Hinzufügen von Knoten zu einem vorhandenen Cluster.

Kubernetes-Version:

Der anfällige Code ist in Kubernetes 1.19 enthalten. Die spezifische Zeile, die den Anruf an klog wurde zuletzt am 24.03.2019 bearbeitet.

Einzelheiten:

Der angreifbare Code befindet sich im github.com/kubernetes Repository in der Datei kubernetes/cmd/kubeadm/app/cmd/token.go in Zeile 423. Hier ist die ganze Funktion:

// 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
}

Und hier ist die Definition des kubeadm-Befehls, der diese Funktion aufruft (in derselben Datei):

    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)
        },
    }

Auswirkung:

Ein Angreifer, der ein Bootstrap-Token aus den Protokollen erhält, könnte sich damit bei kubeadm authentifizieren und einen neuen Cluster erstellen oder Knoten zu einem bestehenden Cluster hinzufügen, um zB Rechenressourcen zu nutzen. Ein Angreifer könnte mit kubeadm auch andere Aktionen ausführen, zB andere Token auflisten oder löschen.

Weitere Informationen:

Ich habe HackerOne diese Sicherheitsanfälligkeit

Ich habe eine PR auf Kubernetes geöffnet, die einen Fix implementiert: https://github.com/kubernetes/kubernetes/pull/94727

aresecurity kincleanup prioritbacklog

Alle 3 Kommentare

Der Löschbefehl von kubeadm verwendet als Eingabe entweder eine Bootstrap-Token-ID oder ein vollständiges Token. Bevor festgestellt wird, ob die Eingabe nur eine ID oder ein vollständiges Token ist, protokolliert kubeadm die Eingabe mit klog. Wenn das Löschen fehlschlägt, bleibt das Token gültig. Ein Angreifer, der Zugriff auf die Protokolle hat, könnte damit Aktionen ausführen, die ein Bootstrap-Token erfordern, z. B. das Erstellen eines Clusters oder das Hinzufügen von Knoten zu einem vorhandenen Cluster.

Hallo, und danke für die Anmeldung des Problems. Um solche Protokolle lesen zu können, müsste man die richtigen Berechtigungen haben und ich würde annehmen, dass die Protokolle entweder unter Root-Zugriff stehen oder an eine bestimmte Gruppe weitergegeben werden, die bereits einen höheren Zugriff als Bootstrap-Token hat.

Auch:

  • --v=>1 muss während der Ausführung von kubeadm token delete aktiviert werden, wenn das Token ein gültiges Format hat
  • Token verfallen standardmäßig nach 24 Stunden

Ich denke, die Verbesserung der PR ist größtenteils in Ordnung, aber ich denke nicht, dass wir aufgrund der Komplexität eines solchen Angriffs auf ältere Releases (<1.20) zurückportieren sollten.

Ich stimme @neolit123 zu, nicht zurück zu portieren (es sei denn, es gibt wirklich spezielle Anforderungen)
WRT zum Fix, ich bin +1, um die TokenID aus den Protokollen zu entfernen

wird geschlossen, da https://github.com/kubernetes/kubernetes/pull/94727 zusammengeführt wurde.
Danke

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen