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-history-store-path — Apache Spark 4.2.0 - Alta - Remoto - Gravação de arquivo - History appStorePath App ID não sanitizado | Kitploit
Ferramentas/GitHubGitHub/abraxas/spark-history-store-path
Análise EstáticaAnálise de VulnerabilidadesAnálise de CódigoExploraçãoExploração de Aplicações WebTestes de PenetraçãoLabs e Prática
GitHub
abraxas/spark-history-store-path

spark-history-store-path

Apache Spark 4.2.0 - Alta - Remoto - Gravação de arquivo - History appStorePath App ID não sanitizado

Ver Repositório
16há 10 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-history-store-path

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  spark-history-store-path

Write-up: https://abraxaslabs.tech/research/spark-history-store-path

spark-history-store-path

Classe: Escrita de arquivo (condicionada por configuração) Alcance: Remoto

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

HistoryServerDiskManager.appStorePath executa new File(appStoreDir, appId + extension) sem sanitização. Utils.sanitizeDirName serve apenas para nomes de arquivo de event-log. O App ID do JSON é asText(). A listagem armazena event.appId.orNull. Lease.commit usa essa string. O App ID ../ grava um .rdb fora de spark.history.store.path. O padrão não definido de store.path é em memória (sem escrita). O conteúdo é um arquivo de store, não RCE.

IDainda sem CVE
ClasseEscrita de arquivo (store em disco do History condicionado por configuração)
AlcanceRemoto (escritor de event-log mais History com spark.history.store.path definido; ACLs da UI desativadas por padrão)
CWECWE-22
CVSSAlto: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N quando spark.history.store.path está definido
ProdutoApache Spark History Server
Afetado4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
Autenticaçãoescritor de spark.history.fs.logDirectory (padrão file:/tmp/spark-events); o History deve ter spark.history.store.path definido
LicençaGNU Affero GPL v3.0
Labapenas 127.0.0.1:18990. Gadget da junção citada. Testemunha .rdb fora de store.path.

O que um atacante pode fazer

Mesmo modelo de vítima do CVE-2025-54920: History Server apontado para um diretório de logs no qual o atacante pode escrever. O Jackson não constrói mais gadgets da classe HiveConnection. O caminho do disk-store ainda confia no App ID do JSON de eventos.

MétodoSinkPrivilégioLab vs inferido
Plantar um event log cujo JSON App ID é ../<name> (ou ../../oracle/...). Aguardar o scan. GET que carrega a UI do app / getAppUI / loadDiskStore / createDiskStoreHistoryServerDiskManager.appStorePath e depois Lease.commit renameToIntegridade: criar um caminho .rdb (RocksDB por padrão) ou .ldb (LevelDB) fora de {store.path}/apps como o History UID. Comprovado em lab no gadget: escaped=yes, o arquivo /work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb contém a testemunha. O conteúdo é um arquivo de store, não bytecode de host escolhido pelo atacante, não um shell.Comprovado em lab (gravação de bytes de testemunha pelo gadget no caminho escapado). O renameTo completo do History de um diretório RocksDB é o mesmo join.
Mesmo App ID quando o destino escapado já é um diretórioLease.commit if (dst.isDirectory()) deleteStore(dst) e depois Utils.deleteRecursivelyDisponibilidade: excluir um diretório existente cujo nome já termina no sufixo do backend e, em seguida, substituí-lo pelo store arrendado.Inferido (fixar HistoryServerDiskManager.scala commit). O gadget gravou um arquivo, não chamou deleteRecursively.
spark.history.store.path padrão não definidoLOCAL_STORE_DIR createOptional; diskManager = storePath.mapFechado. Listagem em memória. Sem HistoryServerDiskManager. Comprovado em lab gated=yes written=no.Comprovado em lab
Aplicar Utils.sanitizeDirName ao App ID primeirohelper do nome do arquivo de event-logPermanece dentro de apps/. / e : tornam-se -. Comprovado em lab negativo.Comprovado em lab
Controlar App ID local-control com store.path definidomesmo joinGrava {store.path}/apps/local-control.rdb. Permanece dentro de apps/.Comprovado em lab

Fechados adjacentes: store padrão não definido (em memória). Jackson sparkEventFromJson ainda exige SparkListenerEvent (CVE-2025-54920). O fallback de URL getAppUI eventlog_v2_ + nameForAppAndAttempt é sanitizado. A chave KV de listagem não é um caminho de filesystem. O mapper HybridStore / kvstore não tem Id.CLASS. O History HTTP não aceita um caminho de upload. Compactação desativada por padrão. Cleaner desativado por padrão. Submissão de job em um cluster aberto (SECURITY.md FAQ). Carregamento de modelo ML (docs/ml-security.md). Este resíduo não é RCE de host.

Como eu encontrei

Eu fixei o Spark 4.2.0, não o master, não um RC 4.3. Vinte e oito caçadas. O RCE público do History Jackson está fechado nesta camada. Os escritores de event-log já chamam Utils.sanitizeDirName, então o arquivo de log não pode conter /. O nome do arquivo de disk-cache usa o App ID bruto.

private[history] def appStorePath(appId: String, attemptId: Option[String]): File = {
  val fileName = appId + attemptId.map("_" + _).getOrElse("") + extension
  new File(appStoreDir, fileName)
}

appStoreDir é {spark.history.store.path}/apps. No Unix, new File(parent, "../../oracle/name.rdb") é resolvido fora do parent. JsonProtocol.applicationStartFromJson usa json.get("App ID").asText(). AppListingListener.onApplicationStart armazena event.appId.orNull. lease.commit(appId, attempt.info.attemptId) alimenta essa string para appStorePath.

Caminhos errados já registrados: tratar o store.path padrão não definido como uma escrita (ele está em memória); esperar que no Unix new File(dir, "/abs") ignore o parent (não ignora; o que sobra é ..); alegar RCE porque o sufixo é .rdb; inicializar um History Server completo quando o join é o oracle; tratar sanitizeDirName como se cobrisse esse caminho.

Lab

python3 spark-history-store-path-Abraxas-Labs.py

ou

cd lab
./run.sh

Gadget de HistoryServerDiskManager.appStorePath em 127.0.0.1:18990. Fixe os trechos em lab/pin/. O History Server completo não é inicializado. Vincule-o ao loopback.

SUCCESS SPARK-HISTORY-STORE-PATH how=gadget escaped=yes gated=yes outside=/work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb SPARK-HISTORY-STORE-PATH-WITNESS

A correção

Execute Utils.sanitizeDirName (ou rejeite .. / / / NUL) em appId e attemptId dentro de appStorePath antes de new File. Após o join, exija que dst.getCanonicalFile() permaneça sob appStoreDir.getCanonicalFile(). spark.history.store.path não definido continua sendo o padrão seguro.

Referências

Baixar ferramenta