Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
spark-history-store-path — Apache Spark 4.2.0 — высокий уровень — удалённо — запись файла — History appStorePath несанитизированный App ID | Kitploit
Инструменты/GitHubGitHub/abraxas/spark-history-store-path
Статический анализАнализ уязвимостейАнализ КодаЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеЛаборатории и Практика
GitHub
abraxas/spark-history-store-path

spark-history-store-path

Apache Spark 4.2.0 — высокий уровень — удалённо — запись файла — History appStorePath несанитизированный App ID

Репозиторий
1610 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Abraxas Labs - spark-history-store-path

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

Разбор: https://abraxaslabs.tech/research/spark-history-store-path

spark-history-store-path

Класс: запись файлов (зависит от конфигурации) Достижимость: удалённая

Apache Spark 4.2.0 (32f72996) — Apache Software Foundation

HistoryServerDiskManager.appStorePath выполняет new File(appStoreDir, appId + extension) без какой-либо очистки. Utils.sanitizeDirName применяется только к именам файлов журнала событий. JSON-поле App ID обрабатывается через asText(). При листинге сохраняется event.appId.orNull. Lease.commit использует эту строку. App ID ../ записывает .rdb за пределами spark.history.store.path. По умолчанию незаданный store.path хранится в памяти (без записи). Содержимое представляет собой файл хранилища, а не RCE.

IDCVE пока нет
КлассЗапись файлов (дисковое хранилище History, зависит от конфигурации)
ДостижимостьУдалённая (запись журнала событий плюс History с заданным spark.history.store.path; ACL интерфейса по умолчанию отключены)
CWECWE-22
CVSSВысокий: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N при заданном spark.history.store.path
ПродуктApache Spark History Server
Затронуто4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
Аутентификациязапись в spark.history.fs.logDirectory (по умолчанию file:/tmp/spark-events); в History должен быть задан spark.history.store.path
ЛицензияGNU Affero GPL v3.0
Лабораториятолько 127.0.0.1:18990. Гадже́т упомянутого объединения. Свидетель .rdb вне store.path.

Что может сделать атакующий

Та же модель жертвы, что и в CVE-2025-54920: History Server указывает на каталог журналов, в который атакующий может писать. Jackson больше не создаёт гаджеты класса HiveConnection. Путь дискового хранилища по-прежнему доверяет App ID из JSON событий.

МетодСтокПривилегияЛаборатория vs вывод
Подложить журнал событий, чей JSON App ID равен ../<name> (или ../../oracle/...). Дождаться сканирования. GET, который загружает UI приложения / getAppUI / loadDiskStore / createDiskStoreHistoryServerDiskManager.appStorePath, затем Lease.commit renameToЦелостность: создать путь .rdb (по умолчанию RocksDB) или .ldb (LevelDB) вне {store.path}/apps под UID History. Доказано в лаборатории на гаджете: escaped=yes, файл /work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb содержит свидетельство. Содержимое — это файл хранилища, а не выбранный атакующим байткод хоста, не shell.Доказано в лаборатории (запись байтов-свидетелей гаджетом по экранированному пути). Полный renameTo History для каталога RocksDB — тот же join.
Тот же App ID, когда экранированный пункт назначения уже является каталогомLease.commit if (dst.isDirectory()) deleteStore(dst), затем Utils.deleteRecursivelyДоступность: удалить существующий каталог, имя которого уже заканчивается на суффикс бэкенда, затем заменить его арендованным хранилищем.Выведено (закреплено в коммите HistoryServerDiskManager.scala). Гаджет записал файл, но не вызывал deleteRecursively.
По умолчанию неустановленный spark.history.store.pathLOCAL_STORE_DIR createOptional; diskManager = storePath.mapЗакрыто. Листинг в памяти. Нет HistoryServerDiskManager. Доказано в лаборатории gated=yes written=no.Доказано в лаборатории
Применить Utils.sanitizeDirName к App ID заранеепомощник имени файла журнала событийОстаётся внутри apps/. / и : становятся -. Доказано в лаборатории как отрицательный результат.Доказано в лаборатории
Управляющий App ID local-control при установленном store.pathтот же joinЗаписывает {store.path}/apps/local-control.rdb. Остаётся внутри apps/.Доказано в лаборатории

Смежное закрыто: неустановленное хранилище по умолчанию (в памяти). Jackson sparkEventFromJson по-прежнему требует SparkListenerEvent (CVE-2025-54920). Резервный путь URL getAppUI eventlog_v2_ + nameForAppAndAttempt санитизируется. Ключ KV листинга не является путём файловой системы. У маппера HybridStore / kvstore нет Id.CLASS. History HTTP не принимает путь загрузки. Компакция по умолчанию выключена. Очистка по умолчанию выключена. Отправка заданий в открытом кластере (SECURITY.md FAQ). Загрузка ML-модели (docs/ml-security.md). Этот остаток не является RCE хоста.

Как я это нашёл

Я закрепил Spark 4.2.0, не master и не 4.3 RC. Двадцать восемь поисков. Публичный History Jackson RCE закрыт на этой итерации. Писатели журналов событий уже вызывают Utils.sanitizeDirName, поэтому файл журнала не может содержать /. Имя файла дискового кэша использует необработанный App ID.

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. В Unix new File(parent, "../../oracle/name.rdb") разрешается за пределы родительского каталога. JsonProtocol.applicationStartFromJson вызывает json.get("App ID").asText(). AppListingListener.onApplicationStart сохраняет event.appId.orNull. lease.commit(appId, attempt.info.attemptId) передаёт эту строку в appStorePath.

Уже зафиксированные ошибочные пути: трактовка неустановленного по умолчанию store.path как записи (он находится в памяти); ожидание, что Unix new File(dir, "/abs") проигнорирует родительский каталог (это не так; остаётся ..); утверждение о RCE из-за суффикса .rdb; запуск полного History Server, когда соединение и есть oracle; трактовка sanitizeDirName как покрывающего этот путь.

Лаборатория

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

или

cd lab
./run.sh

Гаджет HistoryServerDiskManager.appStorePath на 127.0.0.1:18990. Закрепите фрагменты в lab/pin/. Полный History Server не загружается. Привяжите его к 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

Исправление

Запустите Utils.sanitizeDirName (или отклоните .. / / / NUL) для appId и attemptId внутри appStorePath перед new File. После объединения потребуйте, чтобы dst.getCanonicalFile() оставался внутри appStoreDir.getCanonicalFile(). Неустановленный spark.history.store.path остаётся безопасным значением по умолчанию.

Ссылки

Скачать инструмент