Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
spark-history-store-path — Apache Spark 4.2.0 - Hoch - Remote - Dateischreiben - History appStorePath nicht bereinigte App-ID | Kitploit
Tools/GitHubGitHub/abraxas/spark-history-store-path
Statische AnalyseSchwachstellenanalyseCode-AnalyseExploitationWebanwendungs-ExploitationPenetrationstestsLabs & Praxis
GitHubabraxas/spark-history-store-path

spark-history-store-path

Apache Spark 4.2.0 - Hoch - Remote - Dateischreiben - History appStorePath nicht bereinigte App-ID

Repository anzeigen
16vor 10 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

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

Klasse: Dateischreiben (konfigurationsgesteuert) Reichweite: Remote

Apache Spark 4.2.0 (32f72996) – Apache Software Foundation

HistoryServerDiskManager.appStorePath führt new File(appStoreDir, appId + extension) ohne Bereinigung aus. Utils.sanitizeDirName gilt nur für Event-Log-Dateinamen. Die JSON-App ID wird per asText() gelesen. Die Auflistung speichert event.appId.orNull. Lease.commit verwendet diesen String. Eine App ID ../ schreibt eine .rdb außerhalb von spark.history.store.path. Das standardmäßig nicht gesetzte store.path liegt im Arbeitsspeicher (kein Schreiben). Der Inhalt ist eine Store-Datei, keine RCE.

IDnoch keine CVE
KlasseDateischreiben (konfigurationsgesteuerter History-Disk-Store)
ReichweiteRemote (Event-Log-Schreiber plus History mit gesetztem spark.history.store.path; UI-ACLs standardmäßig deaktiviert)
CWECWE-22
CVSSHoch: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N, wenn spark.history.store.path gesetzt ist
ProduktApache Spark History Server
Betroffen4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
AuthSchreiber von spark.history.fs.logDirectory (Standard file:/tmp/spark-events); History muss spark.history.store.path gesetzt haben
LizenzGNU Affero GPL v3.0
Labnur 127.0.0.1:18990. Gadget des zitierten Joins. Nachweis einer .rdb außerhalb von store.path.

Was ein Angreifer tun kann

Gleiches Opfermodell wie bei CVE-2025-54920: Der History Server zeigt auf ein Log-Verzeichnis, in das der Angreifer schreiben kann. Jackson konstruiert keine Gadgets der Klasse HiveConnection mehr. Der Disk-Store-Pfad vertraut weiterhin der App ID aus dem Event-JSON.

MethodeSinkBerechtigungLabor vs. abgeleitet
Ein Ereignisprotokoll einpflanzen, dessen JSON App ID ../<name> (oder ../../oracle/...) ist. Auf Scan warten. GET, das die App-UI lädt / getAppUI / loadDiskStore / createDiskStoreHistoryServerDiskManager.appStorePath, dann Lease.commit renameToIntegrität: Erstellen eines .rdb-Pfads (Standard RocksDB) oder .ldb-Pfads (LevelDB) außerhalb von {store.path}/apps als History-UID. Im Labor am Gadget nachgewiesen: escaped=yes, Datei /work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb enthält den Witness. Der Inhalt ist eine Store-Datei, kein vom Angreifer gewählter Host-Bytecode, keine Shell.Im Labor nachgewiesen (Gadget schreibt Witness-Bytes an den ausgebrochenen Pfad). Das vollständige History-renameTo eines RocksDB-Verzeichnisses ist derselbe Join.
Dieselbe App ID, wenn das ausgebrochene Ziel bereits ein Verzeichnis istLease.commit if (dst.isDirectory()) deleteStore(dst), dann Utils.deleteRecursivelyVerfügbarkeit: Löschen eines bestehenden Verzeichnisses, dessen Name bereits mit dem Backend-Suffix endet, und anschließendes Ersetzen durch den geleasten Store.Abgeleitet (Pin HistoryServerDiskManager.scala Commit). Das Gadget schrieb eine Datei, rief deleteRecursively nicht auf.
Standardmäßig nicht gesetztes spark.history.store.pathLOCAL_STORE_DIR createOptional; diskManager = storePath.mapGeschlossen. In-Memory-Auflistung. Kein HistoryServerDiskManager. Im Labor nachgewiesen gated=yes written=no.Im Labor nachgewiesen
Zuerst Utils.sanitizeDirName auf die App ID anwendenEvent-Log-Dateinamen-HelferBleibt innerhalb von apps/. / und : werden zu -. Im Labor nachgewiesenes Negativ.Im Labor nachgewiesen
Kontroll-App-ID local-control mit gesetztem store.pathderselbe JoinSchreibt {store.path}/apps/local-control.rdb. Bleibt innerhalb von apps/.Im Labor nachgewiesen

Angrenzend geschlossen: Standardmäßig nicht gesetzter Store (In-Memory). Jackson sparkEventFromJson erfordert weiterhin SparkListenerEvent (CVE-2025-54920). URL-getAppUI-Fallback eventlog_v2_ + nameForAppAndAttempt ist bereinigt. Der Listing-KV-Schlüssel ist kein Dateisystempfad. HybridStore / kvstore-Mapper hat kein Id.CLASS. History-HTTP akzeptiert keinen Upload-Pfad. Compaction standardmäßig aus. Cleaner standardmäßig aus. Job-Submit auf einem offenen Cluster (SECURITY.md FAQ). ML-Modell-Laden (docs/ml-security.md). Dieser Rest ist kein Host-RCE.

Wie ich es gefunden habe

Ich habe Spark 4.2.0 gepinnt, nicht master, nicht ein 4.3 RC. Achtundzwanzig Jagden. Das öffentliche History-Jackson-RCE ist auf diesem Peel geschlossen. Event-Log-Writer rufen bereits Utils.sanitizeDirName auf, sodass die Logdatei kein / enthalten kann. Der Dateiname des Disk-Cache verwendet die rohe App ID.

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

appStoreDir ist {spark.history.store.path}/apps. Unix new File(parent, "../../oracle/name.rdb") wird außerhalb des übergeordneten Verzeichnisses aufgelöst. JsonProtocol.applicationStartFromJson verwendet json.get("App ID").asText(). AppListingListener.onApplicationStart speichert event.appId.orNull. lease.commit(appId, attempt.info.attemptId) speist diesen String in appStorePath ein.

Bereits dokumentierte Fehlannahmen: das standardmäßig nicht gesetzte store.path als Schreibvorgang zu behandeln (es ist im Arbeitsspeicher); zu erwarten, dass Unix new File(dir, "/abs") das übergeordnete Verzeichnis ignoriert (das tut es nicht; übrig bleibt ..); RCE zu behaupten, weil das Suffix .rdb lautet; einen vollständigen History Server zu starten, obwohl der Join das Oracle ist; sanitizeDirName als Abdeckung dieses Pfads zu betrachten.

Lab

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

oder

cd lab
./run.sh

Gadget von HistoryServerDiskManager.appStorePath auf 127.0.0.1:18990. Pin-Auszüge unter lab/pin/. Der vollständige History Server wird nicht gestartet. Binden Sie ihn an 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

Die Behebung

Führen Sie Utils.sanitizeDirName (oder lehnen Sie .. / / / NUL ab) auf appId und attemptId innerhalb von appStorePath vor new File aus. Nach dem Join muss dst.getCanonicalFile() unter appStoreDir.getCanonicalFile() bleiben. Ein nicht gesetztes spark.history.store.path bleibt der sichere Standard.

Referenzen

Tool herunterladen