Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-64640 — Reprodutor para CVE-2026-64640 — Apache Polaris Iceberg REST register/register-view fornece credenciais de armazenamento e lê um local de metadados escolhido pelo atacante antes de validar allowedLocations (leitura entre locatários por confusão de subordinado). Afetado ≤ 1.6.0, corrigido em 1.7.0. | Kitploit
Ferramentas/GitHubGitHub/oscerd/cve-2026-64640
ReconhecimentoAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebExfiltração de DadosTestes de PenetraçãoSegurança na NuvemSegurança de API
GitHuboscerd/cve-2026-64640

CVE-2026-64640

Ver Repositório
14há 1 mêsAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →

Sobre

Reprodutor para CVE-2026-64640 — Apache Polaris Iceberg REST register/register-view fornece credenciais de armazenamento e lê um local de metadados escolhido pelo atacante antes de validar allowedLocations (leitura entre locatários por confusão de subordinado). Afetado ≤ 1.6.0, corrigido em 1.7.0.

Compartilhar

CVE-2026-64640 — Apache Polaris: emissão de credenciais antes da validação de localização em register

Um reprodutor autocontido, acionado com um único comando, para a CVE-2026-64640: os endpoints register do Iceberg REST no Apache Polaris emitem credenciais de armazenamento em nuvem para um caminho fornecido pelo chamador e leem esse caminho no lado do servidor antes de verificá-lo em relação aos allowedLocations do catálogo.

Um principal cujo único privilégio é criar tabelas em seu próprio catálogo pode fazer o Polaris usar as credenciais de armazenamento do catálogo para ler objetos que o catálogo nunca teve permissão de tocar — o prefixo de outro tenant, outro bucket, qualquer coisa que o principal de armazenamento consiga alcançar.

CVECVE-2026-64640
Componentepolaris-runtime-service — IcebergCatalog / LocalIcebergCatalog: registerTable, registerView
EndpointsPOST /api/catalog/v1/{prefix}/namespaces/{namespace}/register
POST /api/catalog/v1/{prefix}/namespaces/{namespace}/register-view (1.6.0+)
CWECWE-441 (deputado confuso), CWE-639 (bypass de autorização por meio de chave controlada pelo usuário), CWE-918 (SSRF)
GravidadeAlta — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N (8.1)
Afetadas≤ 1.6.0 (verificado em 1.3.0-incubating, 1.4.0, 1.4.1, 1.5.0, 1.6.0)
Corrigida em1.7.0 — a 1.6.0 corrige apenas o caminho de tabela e reintroduz a falha no novo caminho de view
Privilégio necessárioum principal autenticado com TABLE_CREATE / CATALOG_MANAGE_CONTENT em qualquer catálogo — sem admin

A 1.6.0 não é uma correção. Ela fecha o register (incidentalmente, dentro de um PR de funcionalidade) e entrega o recém-criado endpoint register-view com o mesmo erro de ordenação. O reprodutor prova as duas metades. Atualize para a 1.7.0.

Como executar

Pré-requisitos: Docker com o plugin Compose v2, curl, python3, bash. Nada mais — o ambiente é construído a partir de imagens publicadas e derrubado em seguida.

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

O código de saída 0 significa que a vulnerabilidade foi reproduzida, 1 significa que não foi, 2 significa que o ambiente não conseguiu subir. Cada requisição e resposta é gravada em evidence/<timestamp>-polaris-<tag>/.

Como é o ambiente

  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

Essa última linha é a parte realista. Os operadores delimitam um catálogo com allowedLocations; a role de IAM subjacente é quase sempre mais ampla do que um único prefixo. allowedLocations é a parede. Este bug a contorna.

O que ele prova

Teste 0 — a parede é real. Criar uma tabela com uma localização explícita em s3://tenant-b-private é recusado com 403 ForbiddenException, antes que qualquer coisa seja lida. O Polaris sabe muito bem que a localização está fora dos limites.

Teste 1 — o register lê mesmo assim. O mesmo principal aponta register para s3://tenant-b-private/sales/metadata/00007-tenant-b-sales.metadata.json. A resposta também é um 403 — mas ela cita s3://tenant-b-private/warehouse/CANARY-64640-4f1c9e2a-tenant-b-sales, uma string que existe apenas no corpo daquele objeto:

{"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}}

A requisição nunca menciona warehouse/. O Polaris só poderia produzir essas strings buscando e analisando o objeto com as credenciais do catálogo. O 403 é o Polaris capturando a violação um passo depois da leitura que deveria prevenir.

Teste 2 — o que volta. Dois campos distintos extraídos do documento vítima são ecoados de volta ao chamador: a location declarada da tabela e sua propriedade write.data.path.

Teste 3 — um oráculo de enumeração de armazenamento. A mesma chamada responde de forma diferente para cada estado de um alvo fora de allowedLocations:

sonda (todas fora de allowedLocations)resposta da 1.4.1
metadados Iceberg válidos, existem403 ForbiddenException + localizações analisadas ecoadas
chave ausente400 NotFoundException — Location does not exist: …
bucket não existe400 NoSuchBucketException — erro bruto do SDK S3
existe, mas não é metadado Iceberg503 RuntimeIOException — Failed to read file: …

Quatro respostas distinguíveis significam quatro fatos sobre o armazenamento que o chamador não tem o direito de aprender. Em AWS real, a sonda de existência de bucket alcança o namespace global de buckets S3, usando as credenciais do catálogo.

Em uma build corrigida, cada linha dessa tabela é o mesmo 403 mencionando apenas o caminho solicitado, e nada de dentro do objeto volta — o script detecta essa assinatura e reporta NOT VULNERABLE — pre-validation observed.

Teste 4 — a mesma falha em register-view. O Polaris 1.6.0 adicionou POST .../namespaces/{ns}/register-view, alcançando o registerView, que carrega o FileIO e analisa o documento do chamador sem validação prévia — exatamente o que o registerTable tinha acabado de parar de fazer. Na 1.6.0, o canário de view volta:

{"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}}

Portanto, uma implantação na 1.6.0 ainda está exposta, por meio de um endpoint diferente, à mesma primitiva. Na 1.4.1 e em versões anteriores, o endpoint não existe e o script informa isso.

Causa raiz

IcebergCatalog.registerTable (LocalIcebergCatalog a partir da 1.6.0), antes da correção — registerView tem exatamente a mesma forma:

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

A cadeia de emissão (loadFileIOForTableLike → StorageAccessConfigProvider.getStorageAccessConfig → *StorageIntegration.getSubscopedCreds) não realiza nenhuma verificação própria de allowedLocations; portanto, a única aplicação é a do momento do commit — e nesse ponto a leitura privilegiada já aconteceu e o resultado dela está na resposta.

Baixar ferramenta