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

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

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

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

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

Категории

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

spark-history-zip-symlink

Apache Spark 4.2.0 — высокий уровень — удалённо — чтение файла — History zip следует по подложенной символической ссылке

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

Популярное

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

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

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

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

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

Abraxas Labs - spark-history-zip-symlink

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

spark-history-zip-symlink

Класс: чтение файлов Достижимость: удалённая

Apache Spark 4.2.0 (32f72996) — Apache Software Foundation

CVE-2025-54920 закрыл Jackson в History Server, поэтому sparkEventFromJson теперь создаёт только подклассы SparkListenerEvent. При этом zipEventLogFiles по-прежнему выгружает каждого потомка из listStatus через FileSystem.open. LocalFileSystem следует по POSIX-симлинку. Подложенный потомок в eventlog_v2_* упаковывается в неаутентифицированный GET /api/v1/applications/{id}/logs. Тело элемента zip — это цель SHS-UID. Имя записи — это basename симлинка.

Это не повторная отправка Jackson RCE. Jackson остаётся закрытым. Это не RCE на хосте. Целостность и доступность не затронуты.

IDCVE пока нет
Классчтение файлов (остаток от rolling zip в модели жертвы CVE-2025-54920)
Достижимостьудалённая (запись в каталог логов History плюс неаутентифицированный GET zip)
CWECWE-59, CWE-22
CVSSHigh: 7.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
ПродуктApache Spark
Затронутотег 4.2.0 v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
АутентификацияPR:L = запись в spark.history.fs.logDirectory (та же жертва, что и в 54920). ACL History UI по умолчанию отключены.
ЛицензияGNU Affero GPL v3.0
Лабораториятолько 127.0.0.1:18980

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

Тот, кто может писать в spark.history.fs.logDirectory (по умолчанию file:/tmp/spark-events), может подложить rolling-каталог, который History Server заархивирует. Rolling-писатели по умолчанию включены. ACL History UI по умолчанию отключены. UID процесса SHS — это confused deputy.

ПривилегияМетод / sinkДоказано в лаборатории или выведено
Конфиденциальность: чтение файла хоста, который может открыть UID SHSПодложить eventlog_v2_<id>/ с валидными appstatus_* и events_* JSON (SparkListenerLogStart / SparkListenerApplicationStart) плюс потомок-симлинк, цель которого находится вне каталога логов. Дождаться сканирования. Неаутентифицированный GET /api/v1/applications/{id}/logs (OneApplicationResource.getEventLogs -> FsHistoryProvider.writeEventLogs -> RollingEventLogFilesFileReader.zipEventLogFiles -> FileSystem.open)Доказано в лаборатории. Тело элемента zip eventlog_v2_app-2026-0001/planted-secret — это SPARK-HISTORY-ZIP-SYMLINK-WITNESS. В элементе events свидетеля нет. Имя записи остаётся basename симлинка, а не путём цели.
Конфиденциальность: лог событий соседнего тенанта, который атакующий не может open (660)Тот же zip, цель симлинка — лог другого приложенияВыведено. Тот же FileSystem.open. Не проверялось.
Конфиденциальность: keytab, spark-env.sh, /etc/passwd, если SHS может их прочитатьТот же zipВыведено. Оракулом служит выделенный /secret/host-secret, а не эти файлы.
Целостность файлов SHS или хостаzip читается в тело HTTP-ответаЗакрыто. Доказано в лаборатории отсутствие.
Доступность файлов SHS или хостаzip не удаляет и не усекает цельЗакрыто. Доказано в лаборатории отсутствие.
RCE на хосте / конструирование Jackson-гаджетаJsonProtocol.sparkEventFromJsonЗакрыто. Требуется SparkListenerEvent. Эта лаборатория подкладывает только безобидный Event JSON.
Zip slip с ../ в имени записиPath.getName()Закрыто. POSIX-имя файла не может содержать /. Запись — eventlog_v2_<id>/<basename>.
Выход по строке пути из resolveLogPathnew Path(logDir, attempt.logPath)Закрыто. Объект Path остаётся внутри настроенного каталога логов. Выход происходит через inode.
Перезапись при компакции / удаление цели cleaner'омspark.history.fs.eventLog.rolling.maxFilesToRetain по умолчанию Integer.MAX_VALUE; cleaner по умолчанию отключёнЗакрыто. Локальный fs.delete симлинка удаляет ссылку, а не цель.
Неаутентифицированная отправка заданий / загрузка ML-моделиSECURITY.md FAQ / docs/ml-security.mdЗакрыто. По замыслу, не этот остаток.

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

Я зафиксировал apache/spark v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8), а не master или 4.3 RC. Двадцать восемь поисков. Jackson History RCE закрыт на этой ревизии (JsonProtocol.scala:965-972). History Server по-прежнему указывал на доступный для записи атакующим каталог логов, что представляет ту же модель жертвы, что и CVE-2025-54920.

zipEventLogFiles архивирует все files, а не только файлы событий:

override def zipEventLogFiles(zipStream: ZipOutputStream): Unit = {
  val dirEntryName = rootPath.getName + "/"
  zipStream.putNextEntry(new ZipEntry(dirEntryName))
  files.foreach { file =>
    addFileAsZipEntry(zipStream, file.getPath, dirEntryName + file.getPath.getName)
  }
}

addFileAsZipEntry — это fileSystem.open, затем transferTo. LocalFileSystem следует по POSIX-симлинкам. getLogDirInfo комментирует «handles symbolic links properly», а затем обходит неразрешённые родительские Path для отображаемого имени.

Уже зафиксированные неверные пути: трактовка SPARK-52381 как всей истории History; размещение свидетеля в events_* (лаборатория на этом падает); ожидание, что запись zip будет содержать путь цели; трактовка префиксного соединения в resolveLogPath как выхода; попытка использовать класс события HiveConnection на этой ревизии.

Лаборатория

python3 spark-history-zip-symlink-Abraxas-Labs.py

или

cd lab
./run.sh

Гаджет выгрузки rolling zip из EventLogFileReaders.scala, а не полный History Server и не официальный образ spark:4.2.0. Он не разбирает Event JSON через Jackson. Loopback 127.0.0.1:18980. Проект Compose spark-history-zip-symlink. Rolling-каталог содержит валидные appstatus_* + events_* (без свидетеля) плюс planted-secret -> /secret/host-secret.

SUCCESS SPARK-HISTORY-ZIP-SYMLINK SPARK-HISTORY-ZIP-SYMLINK-WITNESS

Исправление

Упаковывать только потомков events_* / appstatus_*, а не каждое имя из listStatus. Открывать без следования (O_NOFOLLOW / опции Hadoop no-symlink) и отклонять потомка, realpath которого находится вне spark.history.fs.logDirectory. Помощник для отображаемого имени — это не проверка realpath.

Ссылки

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