Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
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.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
spark-python-ds-static — Apache Spark 4.2.0 - Alta - Remoto - Privilégio remanescente - mapa global de processo do Python Data Source | Kitploit
Ferramentas/GitHubGitHub/abraxas/spark-python-ds-static
Escalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoPós-ExploraçãoPapers e PesquisaRed TeamingDesenvolvimento de PayloadsLabs e Prática
GitHubabraxas/spark-python-ds-static

spark-python-ds-static

Apache Spark 4.2.0 - Alta - Remoto - Privilégio remanescente - mapa global de processo do Python Data Source

Ver Repositório
17há 8 diasAinda 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 →
Compartilhar

Abraxas Labs - spark-python-ds-static

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  spark-python-ds-static

Write-up: https://abraxaslabs.tech/research/spark-python-ds-static

spark-python-ds-static

Classe: Privilégio residual Alcance: Remoto

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

DataSourceManager.dataSourceBuilders é um mapa JVM-global em que o primeiro vence. O SPARK-45917 registra automaticamente Data Sources Python pyspark_* a partir do sys.path do worker de lookup. O isolamento de sessão do Connect mantém os artefatos em SparkFiles/<sessionUUID>/, e o registerPython por sessão permanece em runtimeDataSourceBuilders. O primeiro lookup ainda coloca o diretório SparkFiles da sessão que dispara no sys.path, serializa (pickle) cada DefaultSource e armazena essas classes em cache no objeto companheiro. Depois, um SQL do Connect (ou SQL do Hive Thrift) read.format(name) / USING name executa essa classe como o UID do Spark sem enviar proto Python.

O plantador é um tenant Python do Connect que já tem permissão de Python. A vítima é um tenant somente-SQL no mesmo driver do Connect. Os aliases Java (parquet, csv, json, orc, jdbc) permanecem no caminho do ServiceLoader Java. Plantios posteriores, depois que o mapa está preenchido, não são atualizados. AC:H é o primeiro lookup mais um nome que não seja um alias Java.

IDainda sem CVE
ClassePrivilégio residual (Data Source Python entre sessões como UID do Spark; não é envio de job sem autenticação)
AlcanceRemoto (driver Spark Connect compartilhado)
CWECWE-269, CWE-502
CVSSAlto: 8.8 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
ProdutoApache Spark
Afetado4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) registro estático de Data Source Python
AutenticaçãoTenant Python do Connect (plantador) mais um usuário posterior somente-SQL do Connect / SQL do Hive Thrift (vítima)
LicençaGNU Affero GPL v3.0
Labapenas 127.0.0.1:18970. Arquivo testemunha. Gadget do mapa companheiro.

O que um atacante pode fazer

Manter uma sessão Python do Spark Connect em um driver compartilhado. Plantar pyfiles/pyspark_<name>.py cujo DefaultSource.name() seja um nome curto de conector ausente (delta, iceberg, hudi, ...). Disparar o primeiro lookup de Data Source Python nessa sessão. Toda sessão posterior no mesmo JVM que fizer read.format(name) ou SQL USING name instancia a classe serializada como o UID do Spark no worker do planejador do driver e nos executores.

Esse é o conjunto completo de privilégios. O plantador já executa Python. O residual é que um tenant somente-SQL, que nunca enviou proto de REGISTER_DATA_SOURCE / UDF Python, ainda executa essa classe.

Integridade (comprovada em laboratório)

MétodoDestinoPrivilégio
Plantador: AddArtifacts com nome pyfiles/pyspark_<name>.py e então primeiro format(name) / lookupDataSourceManager.dataSourceBuilders companheiro (objeto DataSourceManager.scala) mais iter_modules de pyspark_* em lookup_data_sources.pyArmazenar em cache o DefaultSource serializado da sessão que dispara, em todo o JVM. Lab: layer='static' trigger='attacker' first-wins=yes.
Vítima: SQL USING <name> / spark.read.format(name) em uma sessão que nunca plantouPythonDataSourceV2 createDataSourceInPythonExecutar essa classe como UID do Spark. Lab: planted_by='attacker' witness_written=True static-cross-session=yes. O arquivo oráculo contém SPARK-PYTHON-DS-STATIC-WITNESS.

Fechado nesta análise (comprovado em laboratório)

MétodoSinkResultado
Plantio posterior de um segundo nome após o mapa preenchidomesmo mapa estáticoFechado. Primeiro vence. Lab: later-lookup found=False, companion ainda apenas delta.
registerPython("alpha") por sessãoruntimeDataSourceBuildersIsolado. Clone copia apenas runtime. Lab: runtime-isolated=yes. Leitura da vítima de alpha é found=False.
Alias Java parquetJava DataSourceRegister ServiceLoaderFechado. Lab: java-alias-closed=yes layer='java'. O mesmo para csv/json/orc/jdbc.

Inferido (mesmos sinks, não o oráculo)

MétodoSinkPrivilégio
USING da vítima após o plantioworkers Python do driver + executorCódigo em todo o cluster como Spark UID. O lab escreve um arquivo testemunha em vez de um payload.
Mesmo caminhocrash / spin do workerDisponibilidade como Spark UID. Não é o High. O High é a execução de código.
Hive Thrift SQL USING em um SparkSession compartilhadomesmo mapa estáticoMesmo resíduo se Thrift e Connect compartilharem a JVM do driver. Não exercitado.

O que este resíduo não concede

  • Submissão de job não autenticada em um cluster aberto. FAQ do SECURITY.md. Por design.
  • Hijack Java de parquet / csv / json / orc / jdbc. ServiceLoader vence.
  • Escape de caminho de artefato (concatenatePaths rejeita .. e nomes absolutos).
  • pythonExec fornecido pelo cliente. O planner do Connect usa PYSPARK_PYTHON / python3 do servidor.
  • Vazamento entre sessões de registerPython. O mapa de runtime é por instância de DataSourceManager.
  • pyspark local de usuário único com uma sessão. Não há outro tenant.
  • Uma busca miss-first que preenche um mapa vazio. Plantios posteriores não atualizam (AC:H).

Como eu encontrei

Fixe em apache/spark v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8). Vinte e oito buscas no código-fonte. A submissão de job executando código do usuário é por design. History Jackson, shell da UI, impersonação local do PySpark e caminho de recebimento RPC standalone estão fechados nesta análise. Artefatos do Connect isolam pyfiles sob um UUID de sessão. registerPython em runtime é por sessão. O objeto companion não é.

SPARK-45917 auto-registra pacotes pyspark_* a partir do PYTHONPATH. Isso é intencional para conectores instalados pelo operador. O resíduo é que o worker de busca também faz sys.path.insert do diretório SparkFiles da sessão que disparou (worker_util.setup_spark_files), e então serializa com pickle qualquer DefaultSource pyspark_* que encontrar em um mapa global de processo que nunca atualiza.

Caminho errado: tratar o isolamento de registerPython como toda a barreira de tenant. O runtime é isolado. O estático não é.

Lab

cd lab
./run.sh

Loopback 127.0.0.1:18970. Projeto Compose spark-python-ds-static. Witness SPARK-PYTHON-DS-STATIC-WITNESS. Gadget Python de object DataSourceManager mais mapas de runtime por sessão. Planta pyspark_delta.py apenas no SparkFiles do atacante. A consulta do atacante preenche o companion. A planta posterior de iceberg não atualiza. A read da vítima de delta grava o oráculo. registerPython("alpha") não vaza. O parquet Java permanece Java.

Última linha:

Baixar ferramenta