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
há 2 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

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 sob SparkFiles/<sessionUUID>/, e o registerPython por sessão permanece em runtimeDataSourceBuilders. O primeiro lookup ainda coloca o diretório SparkFiles da sessão que disparou no sys.path, serializa (pickle) cada DefaultSource e armazena essas classes em cache no objeto companheiro. Depois, o Connect SQL (ou Hive Thrift SQL) read.format(name) / USING name executa essa classe como o Spark UID sem enviar o 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 Connect. Os aliases Java (parquet, csv, json, orc, jdbc) permanecem no caminho do ServiceLoader Java. Plantações posteriores, depois que o mapa está preenchido, não são atualizadas. AC:H é o primeiro lookup mais um nome que não é um alias Java.

IDainda sem CVE
ClassePrivilégio residual (Data Source Python entre sessões como Spark UID; não é envio de job não autenticado)
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 / Hive Thrift SQL (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 na mesma JVM que faça read.format(name) ou SQL USING name instancia a classe serializada como o Spark UID no worker do planner 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 REGISTER_DATA_SOURCE / proto de UDF Python, ainda executa essa classe.

Integridade (comprovada em lab)

MétodoSinkPrivilégio
Plantador: AddArtifacts com nome pyfiles/pyspark_<name>.py e então primeiro format(name) / lookupcompanheiro DataSourceManager.dataSourceBuilders (objeto DataSourceManager.scala) mais lookup_data_sources.py iter_modules de pyspark_*Armazenar em cache o DefaultSource serializado da sessão que disparou, em toda a 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 Spark UID. 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 lab)

MétodoSinkResultado
Plantação posterior de um segundo nome depois que o mapa foi preenchidomesmo mapa estáticoFechado. O primeiro vence. Lab: later-lookup found=False, companheiro ainda apenas delta.
registerPython("alpha") por sessãoruntimeDataSourceBuildersIsolado. O clone copia apenas o runtime. Lab: runtime-isolated=yes. A leitura de alpha pela vítima é found=False.
Alias Java parquetDataSourceRegister ServiceLoader JavaFechado. 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
Vítima USING após a plantaçãoworkers 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 Alto. O Alto é a execução de código.
Hive Thrift SQL USING em um SparkSession compartilhadomesmo mapa estáticoMesmo residual se Thrift e Connect compartilharem a JVM do driver. Não exercitado.

O que este residual não concede

  • Envio de job não autenticado em um cluster aberto. FAQ do SECURITY.md. Por design.
  • Sequestro de parquet / csv / json / orc / jdbc Java. O ServiceLoader vence.
  • Escape do 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.
  • Um lookup que erra primeiro e preenche um mapa vazio. Plantações posteriores não são atualizadas (AC:H).

Como eu encontrei

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

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

Caminho errado: tratar o isolamento do registerPython como toda a barreira entre tenants. 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. Testemunha SPARK-PYTHON-DS-STATIC-WITNESS. Gadget Python de object DataSourceManager mais mapas de runtime por sessão. Plantar pyspark_delta.py apenas no SparkFiles do atacante. O lookup do atacante preenche o companheiro. Plantação posterior de iceberg não é atualizada. A leitura de delta pela vítima escreve o oráculo. registerPython("alpha") não vaza. parquet Java permanece Java.

Última linha:

SUCCESS SPARK-PYTHON-DS-STATIC static-cross-session=yes runtime-isolated=yes first-wins=yes java-alias-closed=yes SPARK-PYTHON-DS-STATIC-WITNESS
Baixar ferramenta