Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
spark-history-store-path — Apache Spark 4.2.0 - Alto - Remoto - Scrittura di file - History appStorePath App ID non sanificato | Kitploit
Strumenti/GitHubGitHub/abraxas/spark-history-store-path
Analisi StaticaAnalisi delle VulnerabilitàAnalisi del CodiceExploitSfruttamento di Applicazioni WebPenetration TestingLab e Pratica
GitHub
abraxas/spark-history-store-path

spark-history-store-path

Apache Spark 4.2.0 - Alto - Remoto - Scrittura di file - History appStorePath App ID non sanificato

Vedi Repository
1610 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

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: Scrittura di file (condizionata dalla configurazione) Portata: Remota

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

HistoryServerDiskManager.appStorePath esegue new File(appStoreDir, appId + extension) senza alcuna sanitizzazione. Utils.sanitizeDirName è usato solo per i nomi dei file di event-log. L'App ID nel JSON viene letto con asText(). L'elenco memorizza event.appId.orNull. Lease.commit usa quella stringa. Un App ID ../ scrive un .rdb al di fuori di spark.history.store.path. Il valore predefinito non impostato di store.path è in memoria (nessuna scrittura). Il contenuto è un file di store, non RCE.

IDnessuna CVE al momento
ClasseScrittura di file (disk store della History condizionato dalla configurazione)
PortataRemota (scrittore dell'event-log più History con spark.history.store.path impostato; ACL della UI disattivate per impostazione predefinita)
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 è impostato
ProdottoApache Spark History Server
Affetto4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
Authscrittore di spark.history.fs.logDirectory (predefinito file:/tmp/spark-events); la History deve avere spark.history.store.path impostato
LicenzaGNU Affero GPL v3.0
Labsolo 127.0.0.1:18990. Gadget del join citato. Witness .rdb al di fuori di store.path.

Cosa può fare un attaccante

Stesso modello di vittima di CVE-2025-54920: History Server puntato a una directory di log in cui l'attaccante può scrivere. Jackson non costruisce più gadget della classe HiveConnection. Il percorso del disk store continua comunque a fidarsi dell'App ID nel JSON dell'evento.

MetodoSinkPrivilegioLab vs dedotto
Impiantare un event log il cui App ID JSON è ../<name> (o ../../oracle/...). Attendere la scansione. GET che carica la UI dell'app / getAppUI / loadDiskStore / createDiskStoreHistoryServerDiskManager.appStorePath poi Lease.commit renameToIntegrità: creare un percorso .rdb (RocksDB predefinito) o .ldb (LevelDB) al di fuori di {store.path}/apps come History UID. Dimostrato in laboratorio sul gadget: escaped=yes, il file /work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb contiene il witness. Il contenuto è un file di store, non bytecode host scelto dall'attaccante, non una shell.Dimostrato in laboratorio (scrittura del witness da parte del gadget al percorso evaso). Il renameTo completo di History di una directory RocksDB è lo stesso join.
Stesso App ID quando la destinazione evasa è già una directoryLease.commit if (dst.isDirectory()) deleteStore(dst) poi Utils.deleteRecursivelyDisponibilità: eliminare una directory esistente il cui nome termina già con il suffisso del backend, poi sostituirla con lo store in lease.Dedotto (pin di HistoryServerDiskManager.scala commit). Il gadget ha scritto un file, non ha chiamato deleteRecursively.
spark.history.store.path predefinito non impostatoLOCAL_STORE_DIR createOptional; diskManager = storePath.mapChiuso. Elenco in memoria. Nessun HistoryServerDiskManager. Dimostrato in laboratorio gated=yes written=no.Dimostrato in laboratorio
Applicare Utils.sanitizeDirName all'App ID primahelper del nome file dell'event logRimane dentro apps/. / e : diventano -. Negativo dimostrato in laboratorio.Dimostrato in laboratorio
Controllare l'App ID local-control con store.path impostatostesso joinScrive {store.path}/apps/local-control.rdb. Rimane dentro apps/.Dimostrato in laboratorio

Adiacenti chiusi: store predefinito non impostato (in memoria). Jackson sparkEventFromJson richiede comunque SparkListenerEvent (CVE-2025-54920). Il fallback URL getAppUI eventlog_v2_ + nameForAppAndAttempt è sanitizzato. La chiave KV dell'elenco non è un percorso filesystem. HybridStore / kvstore mapper non ha Id.CLASS. History HTTP non accetta un percorso di upload. Compaction disattivata per impostazione predefinita. Cleaner disattivato per impostazione predefinita. Invio di job su un cluster aperto (SECURITY.md FAQ). Caricamento di modelli ML (docs/ml-security.md). Questo residuo non è RCE sull'host.

Come l'ho trovato

Ho fissato Spark 4.2.0, non master, non una 4.3 RC. Ventotto ricerche. La RCE pubblica di History Jackson è chiusa su questo livello. I writer degli event log chiamano già Utils.sanitizeDirName quindi il file di log non può contenere /. Il nome del file della cache su disco usa l'App ID grezzo.

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. Su Unix new File(parent, "../../oracle/name.rdb") viene risolto al di fuori della directory padre. JsonProtocol.applicationStartFromJson esegue json.get("App ID").asText(). AppListingListener.onApplicationStart memorizza event.appId.orNull. lease.commit(appId, attempt.info.attemptId) passa quella stringa a appStorePath.

Vicoli ciechi già registrati: considerare la scrittura quando store.path non è impostato e assume il valore predefinito (è in memoria); aspettarsi che su Unix new File(dir, "/abs") ignori la directory padre (non lo fa; ciò che resta è ..); sostenere l'RCE perché il suffisso è .rdb; avviare un History Server completo quando il join è l'oracle; considerare sanitizeDirName come copertura di questo percorso.

Lab

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

o

cd lab
./run.sh

Gadget di HistoryServerDiskManager.appStorePath su 127.0.0.1:18990. Estratti Pin sotto lab/pin/. Il server History completo non è avviato. Associalo al 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

La correzione

Esegui Utils.sanitizeDirName (oppure rifiuta .. / / / NUL) su appId e attemptId all'interno di appStorePath prima di new File. Dopo il join, richiedi che dst.getCanonicalFile() rimanga sotto appStoreDir.getCanonicalFile(). Lasciare spark.history.store.path non impostato resta il default sicuro.

Riferimenti

Scarica lo strumento