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

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

Популярное

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

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

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

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

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

Abraxas Labs - spark-history-store-path

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  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 события.

МетодТочка сбросаПривилегияЛаборатория против вывода
Подложить журнал событий, в JSON которого App ID равен ../<name> (или ../../oracle/...). Дождаться сканирования. GET, который загружает интерфейс приложения / 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 содержит свидетеля. Содержимое — это файл хранилища, а не выбранный атакующим байт-код хоста и не оболочка.Доказано в лаборатории (гаджет записывает байты свидетеля по вырвавшемуся пути). Полный renameTo каталога RocksDB в History — это то же соединение.
Тот же 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то же соединениеЗаписывает {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. Двадцать восемь поисков. Публичный RCE через Jackson в History закрыт на этом срезе. Писатели журналов событий уже вызывают 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") разрешается за пределами parent. 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") проигнорирует parent (это не так; остаток — ..); утверждение об RCE из-за суффикса .rdb; запуск полного History Server, когда соединение и есть оракул; трактовка 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 остаётся безопасным значением по умолчанию.

Ссылки

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