Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
spark-python-ds-static — Apache Spark 4.2.0 - Alta - Remota - Privilegio residual - mapa global de procesos de Python Data Source | Kitploit
Herramientas/GitHubGitHub/abraxas/spark-python-ds-static
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónPost-ExplotaciónPapers e InvestigaciónRed TeamingDesarrollo de PayloadsLabs y Práctica
GitHubabraxas/spark-python-ds-static

spark-python-ds-static

Apache Spark 4.2.0 - Alta - Remota - Privilegio residual - mapa global de procesos de Python Data Source

Ver Repositorio
17hace 8 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Abraxas Labs - spark-python-ds-static

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

Análisis: https://abraxaslabs.tech/research/spark-python-ds-static

spark-python-ds-static

Clase: Privilegio residual Alcance: Remoto

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

DataSourceManager.dataSourceBuilders es un mapa global de la JVM en el que gana el primero. SPARK-45917 registra automáticamente los Python Data Sources pyspark_* desde el sys.path del worker de lookup. El aislamiento de sesión de Connect mantiene los artefactos bajo SparkFiles/<sessionUUID>/, y el registerPython por sesión permanece en runtimeDataSourceBuilders. El primer lookup aun así coloca el directorio SparkFiles de la sesión que lo dispara en sys.path, serializa con pickle cada DefaultSource y almacena en caché esas clases en el objeto companion. Un read.format(name) / USING name posterior de Connect SQL (o Hive Thrift SQL) ejecuta esa clase como el UID de Spark sin enviar proto de Python.

El plantador es un tenant de Connect Python que ya tiene permiso de Python. La víctima es un tenant solo-SQL en el mismo driver de Connect. Los alias de Java (parquet, csv, json, orc, jdbc) permanecen en la ruta del ServiceLoader de Java. Las plantaciones posteriores una vez llenado el mapa no se refrescan. AC:H es el primer lookup más un nombre que no es un alias de Java.

IDaún sin CVE
ClasePrivilegio residual (Python Data Source entre sesiones como UID de Spark; no es envío de trabajos sin autenticación)
AlcanceRemoto (driver de Spark Connect compartido)
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
ProductoApache Spark
Afectado4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) registro estático de Python Data Source
AutenticaciónTenant de Connect Python (plantador) más un usuario posterior solo-SQL de Connect / Hive Thrift SQL (víctima)
LicenciaGNU Affero GPL v3.0
LaboratorioSolo 127.0.0.1:18970. Archivo testigo. Gadget del mapa companion.

Qué puede hacer un atacante

Mantener una sesión de Spark Connect Python en un driver compartido. Plantar pyfiles/pyspark_<name>.py cuyo DefaultSource.name() sea un nombre corto de conector ausente (delta, iceberg, hudi, ...). Disparar el primer lookup de Python Data Source en esa sesión. Cualquier sesión posterior en la misma JVM que ejecute read.format(name) o SQL USING name instancia la clase serializada con pickle como el UID de Spark en el worker del planificador del driver y en los ejecutores.

Ese es el conjunto completo de privilegios. El plantador ya ejecuta Python. Lo residual es que un tenant solo-SQL, que nunca envió proto de REGISTER_DATA_SOURCE / Python UDF, aun así ejecuta esa clase.

Integridad (probado en laboratorio)

MétodoSumideroPrivilegio
Plantador: AddArtifacts con nombre pyfiles/pyspark_<name>.py y luego el primer format(name) / lookupDataSourceManager.dataSourceBuilders del companion (objeto DataSourceManager.scala) más iter_modules de pyspark_* en lookup_data_sources.pyAlmacenar en caché el DefaultSource serializado con pickle de la sesión que lo dispara, a nivel de toda la JVM. Laboratorio: layer='static' trigger='attacker' first-wins=yes.
Víctima: SQL USING <name> / spark.read.format(name) en una sesión que nunca plantóPythonDataSourceV2 createDataSourceInPythonEjecutar esa clase como UID de Spark. Laboratorio: planted_by='attacker' witness_written=True static-cross-session=yes. El archivo oráculo contiene SPARK-PYTHON-DS-STATIC-WITNESS.

Cerrado en este recorrido (probado en laboratorio)

MétodoSinkResultado
Registro posterior de un segundo nombre después de que el mapa se llenómismo mapa estáticoCerrado. Gana el primero. Lab: later-lookup found=False, el companion sigue siendo solo delta.
registerPython("alpha") por sesiónruntimeDataSourceBuildersAislado. El clon copia solo el runtime. Lab: runtime-isolated=yes. La lectura de alpha por la víctima es found=False.
Alias de Java parquetServiceLoader de DataSourceRegister de JavaCerrado. Lab: java-alias-closed=yes layer='java'. Lo mismo para csv/json/orc/jdbc.

Inferido (mismos sinks, no el oráculo)

MétodoSinkPrivilegio
USING de la víctima tras el registroworkers de Python del driver + executorCódigo en todo el clúster como UID de Spark. El lab escribe un archivo testigo en lugar de un payload.
Misma rutacaída / bucle del workerDisponibilidad como UID de Spark. No es el High. El High es la ejecución de código.
SQL de Hive Thrift USING sobre una SparkSession compartidamismo mapa estáticoEl mismo remanente si Thrift y Connect comparten la JVM del driver. No ejercitado.

Lo que este remanente no otorga

  • Envío de jobs sin autenticación en un clúster abierto. FAQ de SECURITY.md. Por diseño.
  • Secuestro de parquet / csv / json / orc / jdbc de Java. Gana ServiceLoader.
  • Escape de ruta de artefactos (concatenatePaths rechaza .. y nombres absolutos).
  • pythonExec proporcionado por el cliente. El planificador de Connect usa PYSPARK_PYTHON / python3 del servidor.
  • Fuga entre sesiones de registerPython. El mapa de runtime es por instancia de DataSourceManager.
  • pyspark local monousuario con una sola sesión. No hay otro inquilino.
  • Una búsqueda que falla primero y llena un mapa vacío. Los registros posteriores no se refrescan (AC:H).

Cómo lo encontré

Fijé apache/spark v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8). Veintiocho búsquedas en el código fuente. Que el envío de jobs ejecute código del usuario es por diseño. Jackson en History, el shell de la UI, la suplantación local de PySpark y la ruta de recepción RPC de standalone están cerrados en esta revisión. Los artefactos de Connect aíslan los pyfiles bajo un UUID de sesión. El registerPython de runtime es por sesión. El objeto companion no lo es.

SPARK-45917 autorregistra paquetes pyspark_* desde PYTHONPATH. Eso está pensado para conectores instalados por el operador. El remanente es que el worker de búsqueda también hace sys.path.insert del directorio SparkFiles de la sesión que lo activa (worker_util.setup_spark_files), y luego serializa con pickle cualquier DefaultSource de pyspark_* que encuentre en un mapa global del proceso que nunca se refresca.

Camino equivocado: tratar el aislamiento de registerPython como toda la barrera entre inquilinos. El runtime está aislado. El estático no.

Lab

cd lab
./run.sh
Descargar herramienta