Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-64640 — Reproducteur pour CVE-2026-64640 — Apache Polaris Iceberg REST register/register-view fournit des identifiants de stockage et lit un emplacement de métadonnées choisi par l'attaquant avant de valider allowedLocations (lecture inter-locataires par député confus). Versions concernées ≤ 1.6.0, corrigé dans 1.7.0. | Kitploit
Outils/GitHubGitHub/oscerd/cve-2026-64640
ReconnaissanceAnalyse des VulnérabilitésExploitationExploitation d'Applications WebExfiltration de DonnéesTests d'IntrusionSécurité CloudSécurité des API
GitHuboscerd/cve-2026-64640

CVE-2026-64640

Voir le dépôt
15il y a 1 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →

À propos

Reproducteur pour CVE-2026-64640 — Apache Polaris Iceberg REST register/register-view fournit des identifiants de stockage et lit un emplacement de métadonnées choisi par l'attaquant avant de valider allowedLocations (lecture inter-locataires par député confus). Versions concernées ≤ 1.6.0, corrigé dans 1.7.0.

Partager

CVE-2026-64640 — Apache Polaris : délivrance d'identifiants avant validation de l'emplacement dans register

Un reproducteur autonome, en une commande, pour CVE-2026-64640 : les points de terminaison register de l'API REST Iceberg dans Apache Polaris génèrent des identifiants de stockage cloud pour un chemin fourni par l'appelant et lisent ce chemin côté serveur avant de le vérifier par rapport aux allowedLocations du catalogue.

Un principal dont le seul privilège est de créer des tables dans son propre catalogue peut amener Polaris à utiliser les identifiants de stockage du catalogue pour lire des objets que le catalogue n'a jamais été autorisé à toucher — le préfixe d'un autre locataire, un autre bucket, tout ce que le principal de stockage peut atteindre.

CVECVE-2026-64640
Composantpolaris-runtime-service — IcebergCatalog / LocalIcebergCatalog : registerTable, registerView
Points de terminaisonPOST /api/catalog/v1/{prefix}/namespaces/{namespace}/register
POST /api/catalog/v1/{prefix}/namespaces/{namespace}/register-view (1.6.0+)
CWECWE-441 (député confus), CWE-639 (contournement d'autorisation via une clé contrôlée par l'utilisateur), CWE-918 (SSRF)
SévéritéÉlevée — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N (8.1)
Versions affectées≤ 1.6.0 (vérifié sur 1.3.0-incubating, 1.4.0, 1.4.1, 1.5.0, 1.6.0)
Corrigé dans1.7.0 — 1.6.0 ne corrige que le chemin table et réintroduit la faille sur le nouveau chemin vue
Privilège requisun principal authentifié disposant de TABLE_CREATE / CATALOG_MANAGE_CONTENT sur n'importe quel catalogue — pas d'administrateur

1.6.0 n'est pas un correctif. Il ferme register (au passage, dans une PR de fonctionnalité) et livre le tout nouveau point de terminaison register-view avec la même erreur d'ordre. Le reproducteur prouve les deux moitiés. Passez à 1.7.0.

Exécution

Prérequis : Docker avec le plugin Compose v2, curl, python3, bash. Rien d'autre — l'environnement est construit à partir d'images publiées puis détruit ensuite.

./exploit.sh                 # default: apache/polaris:1.4.1  -> reproduces via register
./exploit.sh --tag 1.6.0     # partially fixed               -> reproduces via register-view
./exploit.sh --tag 1.7.0     # comprehensively fixed         -> refuses cleanly on both
./scripts/version-matrix.sh  # every release, side by side

Le code de sortie 0 signifie que la vulnérabilité a été reproduite, 1 qu'elle ne l'a pas été, 2 que l'environnement n'a pas pu démarrer. Chaque requête et réponse est écrite dans evidence/<timestamp>-polaris-<tag>/.

À quoi ressemble l'environnement

  catalog  tenant_a_catalog        allowedLocations = [ s3://bucket123 ]
  actor    low_priv_user           CATALOG_MANAGE_CONTENT on that catalog, nothing else
  target   s3://tenant-b-private   another tenant's bucket:
                                     no allowedLocations entry, no grant, no relation
                                     to the attacker's catalog — but reachable by the
                                     credentials that back it

Cette dernière ligne est la partie réaliste. Les opérateurs délimitent un catalogue avec allowedLocations ; le rôle IAM sous-jacent est presque toujours plus large qu'un seul préfixe. allowedLocations est le mur. Ce bug le contourne.

Ce que cela prouve

Test 0 — le mur est réel. La création d'une table avec un emplacement explicite dans s3://tenant-b-private est refusée avec 403 ForbiddenException, avant que quoi que ce soit ne soit lu. Polaris sait parfaitement que l'emplacement est hors limites.

Test 1 — register le lit quand même. Le même principal pointe register vers s3://tenant-b-private/sales/metadata/00007-tenant-b-sales.metadata.json. La réponse est aussi une 403 — mais elle cite s3://tenant-b-private/warehouse/CANARY-64640-4f1c9e2a-tenant-b-sales, une chaîne qui existe uniquement dans le corps de cet objet :

{"error":{"message":"Invalid locations '[s3://tenant-b-private/warehouse/sales/data,
s3://tenant-b-private/warehouse/CANARY-64640-4f1c9e2a-tenant-b-sales]' for identifier
'tenant_a_ns.pwn_canary': s3://tenant-b-private/warehouse/sales/data is not in the list
of allowed locations: [s3://bucket123/tenant_a_ns]","type":"ForbiddenException","code":403}}

La requête ne mentionne jamais warehouse/. Polaris ne pouvait produire ces chaînes qu'en récupérant et en analysant l'objet avec les identifiants du catalogue. La 403 est Polaris qui détecte la violation une étape après la lecture qu'elle était censée empêcher.

Test 2 — ce qui revient. Deux champs distincts extraits du document victime sont renvoyés à l'appelant : la location déclarée de la table et sa propriété write.data.path.

Test 3 — un oracle d'énumération de stockage. Le même appel répond différemment pour chaque état d'une cible hors de allowedLocations :

sonde (toutes hors allowedLocations)réponse 1.4.1
métadonnées Iceberg valides, existantes403 ForbiddenException + emplacements analysés renvoyés
clé manquante400 NotFoundException — Location does not exist: …
bucket inexistant400 NoSuchBucketException — erreur brute du SDK S3
existe mais n'est pas de la métadonnée Iceberg503 RuntimeIOException — Failed to read file: …

Quatre réponses distinguables signifient quatre faits sur le stockage que l'appelant n'a pas le droit d'apprendre. Sur un AWS réel, la sonde d'existence de bucket atteint l'espace de noms global des buckets S3, en utilisant les identifiants du catalogue.

Sur une version corrigée, chaque ligne de ce tableau est la même 403 ne mentionnant que le chemin demandé, et rien ne revient de l'intérieur de l'objet — le script détecte cette signature et rapporte NOT VULNERABLE — pre-validation observed.

Test 4 — la même faille sur register-view. Polaris 1.6.0 a ajouté POST .../namespaces/{ns}/register-view, atteignant registerView, qui charge le FileIO et analyse le document de l'appelant sans validation préalable — précisément ce que registerTable venait de cesser de faire. Sur 1.6.0, le canari de vue revient :

{"error":{"message":"Invalid locations '[s3://tenant-b-private/warehouse/CANARY-64640-VIEW-8d3b7a15-tenant-b]'
for identifier 'tenant_a_ns.pwn_view': … is not in the list of allowed locations:
[s3://bucket123/tenant_a_ns]","type":"ForbiddenException","code":403}}

Une installation 1.6.0 est donc toujours exposée, via un point de terminaison différent, à la même primitive. Sur 1.4.1 et antérieurs, le point de terminaison n'existe pas et le script le signale.

Cause racine

IcebergCatalog.registerTable (LocalIcebergCatalog à partir de 1.6.0), avant le correctif — registerView a la forme identique :

String locationDir = metadataFileLocation.substring(0, lastSlashIndex);   // attacker-controlled
...
FileIO fileIO =
    loadFileIOForTableLike(
        identifier,
        Set.of(locationDir),                                              // credentials minted here
        resolvedParent,
        new HashMap<>(tableDefaultProperties),
        Set.of(PolarisStorageActions.READ, PolarisStorageActions.LIST));

InputFile metadataFile = fileIO.newInputFile(metadataFileLocation);       // server-side GET
TableMetadata metadata = TableMetadataParser.read(metadataFile);          // server-side parse
ops.commit(null, metadata);                                               // allowedLocations checked HERE
Télécharger l’outil