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

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

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

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

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

Категории

Все категории
Loading categories
spark-connect-archive-fragment — Apache Spark 4.2.0 — высокий — удалённый — запись файла — Connect archives hash-fragment dest | Kitploit
Инструменты/GitHubGitHub/abraxas/spark-connect-archive-fragment
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВиртуализация для безопасностиТестирование на ПроникновениеRed TeamingЛаборатории и Практика
GitHub
abraxas/spark-connect-archive-fragment

spark-connect-archive-fragment

Apache Spark 4.2.0 — высокий — удалённый — запись файла — Connect archives hash-fragment dest

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

Популярное

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

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

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

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

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

Abraxas Labs - spark-connect-archive-fragment

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  spark-connect-archive-fragment

spark-connect-archive-fragment

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

Apache Spark 4.2.0 (32f72996) — Apache Software Foundation

Имена AddArtifacts в Spark Connect вида archives/<file>#<fragment> разбиваются по символу решётки / номерного знака. Байты zip проходят через concatenatePaths. Фрагмент — нет. Затем SparkContext.addFile(..., isArchive=true) выполняет new File(root, uri.getFragment), deleteRecursively(dest) и unpack на драйвере. Исполнители строят тот же dest. В SPARK-33530 #name задокументирован как имя каталога под SparkFiles. Фрагмент ../<outside> и есть dest.

Connect archives/<file>#../<path> распаковывает и выполняет deleteRecursively вне каталога SparkFiles сессии от имени Spark UID.

IDCVE пока нет
КлассЗапись файлов
ДостижимостьУдалённая (клиент Spark Connect; AddArtifacts с archive=True)
CWECWE-22
CVSSHigh: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H
ПродуктApache Spark
Затронуто4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) Connect archives/ dest из хеш-фрагмента
АутентификацияКлиент Connect. По умолчанию в Connect нет PSK (spark.connect.authenticate.token не задан). PR:L при PSK / сетевом ACL; PR:N при открытом Connect по умолчанию.
ЛицензияGNU Affero GPL v3.0
Лабораториятолько 127.0.0.1

Я зафиксировал тег v4.2.0 peel 32f72996 (2026-07-11, v4.2.0-rc6). Лаборатория — это Java-гаджет зафиксированного разбиения хеша StagedArtifact, ArtifactUtils.concatenatePaths, new File(root, fragment), deleteRecursively и распаковки zip с ограничением dest. Loopback HTTP на 127.0.0.1:18930. Официальный PySpark уже копирует фрагмент URI в имя архива.

Это не RCE. Элементы zip, выходящие за пределы dest, отклоняются (класс Hadoop FileUtil.unZip / HADOOP-13649). Остаётся сам dest.

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

МетодSinkПривилегия
Connect AddArtifacts имя archives/<file>#../<outside>SparkContext.addFile dest new File(root, uri.getFragment), затем Utils.unpack (SparkContext.scala:1891-1900)Целостность (доказано в лаборатории): запись элементов архива от имени Spark UID вне SparkFiles сессии. Канонический dest лаборатории /lab/oracle/SPARK-CONNECT-ARCHIVE-FRAGMENT-WITNESS, uid 1000, dest-outside=yes.
Тот же dest, до распаковкиUtils.deleteRecursively(dest) (SparkContext.scala:1899)Доступность (доказано в лаборатории): canary в dest исчез. Лаборатория deleteRecursively=yes; canary.txt под dest не сохранился. Соседний /lab/oracle/canary-keep.txt сохранён.
Тот же примитив на каждом исполнителе, который забирает архивExecutor dest new File(root, sourceURI.getFragment), затем deleteRecursively + unpack (Executor.scala:1468-1477)Целостность / доступность (предположительно): то же построение dest на исполнителях. Лаборатория — гаджет на стороне драйвера.
Имя артефакта files/../../... или archives/../../...ArtifactUtils.concatenatePaths (ArtifactUtils.scala:26-39)Закрыто (доказано в лаборатории): INVALID_ARTIFACT_PATH.
Unix-абсолютный фрагмент /absnew File(root, "/abs")Закрыто на Unix (доказано в лаборатории): родитель не игнорируется; dest присоединяется под root. Dest лаборатории /lab/root/lab/oracle/abs-..., outside=false, abs canary сохранён.
Добавление jars/ / classes/ в собственной сессииURLClassLoader сессииЗакрыто как остаточное: загрузка JAR в собственной сессии — по замыслу. Не эта находка.
Загрузка jar между сессиямиИзоляция Connect spark.sql.artifact.isolation.enabled=trueЗакрыто: изолированные сессии читают addedJars(sessionUUID).

Доказано в лаборатории vs предположительно: dest из хеш-фрагмента вне SparkFiles, canary в dest удалён, соседний canary сохранён, конкатенация имён files/ и archives/ отклонена, Unix-абсолютный фрагмент присоединяется под root, uid 1000, распаковка zip с ограничением dest: лаборатория. Забор того же dest исполнителем: предположительно (тот же конструктор). Перезапись позже загруженного класса на classpath драйвера: предполагаемая цепочка, не продемонстрирована, не раздута до RCE.

Требуется: клиент Connect, способный выполнить AddArtifacts с archive=True. Официальный PySpark spark.addArtifact(..., archive=True) уже помещает непустой фрагмент URI в имя (python/pyspark/sql/connect/client/artifact.py:223-236). По умолчанию в Connect нет PSK.

Смежная поверхность, которая остаётся закрытой

ПоверхностьЛаборатория
Имя артефакта .. / абсолютный путь через concatenatePathsfiles-concat=rejected INVALID_ARTIFACT_PATH
Обход имени archives/ archives/../../...тот же INVALID_ARTIFACT_PATH
Unix new File(root, "/abs")dest под root; abs oracle canary сохранён
Zip-slip элемента zip под ограниченным destгаджет отклоняет элементы, выходящие за dest (класс HADOOP-13649). Не это остаточное.
Конкатенация пути files/ (без разбиения по хешу)фрагмент не берётся; имя всё ещё concatenatePaths
Изоляция jar между сессиямипо умолчанию включена для Connect
Неаутентифицированный SQL / Python на открытом Connectотправка заданий по замыслу (SECURITY.md FAQ). Не это остаточное.
Отправка заданий / загрузка ML-моделипо замыслу

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

StagedArtifact разбивает только имена, начинающиеся с archives плюс серверный File.separator, и только по #:

val splits = name.split("#")
if (splits.length == 2) {
  (splits(0), Some(splits(1)))
}

splits(0) размещается через concatenatePaths. splits(1) сохраняется как fragment. ArtifactManager прикрепляет этот фрагмент к URI файлового сервера сессии и вызывает SparkContext.addArchive. Dest — это new File(root, uri.getFragment). В SPARK-33530 тестируется sc.addArchive(s"${jarFile.getAbsolutePath}#foo") как имя каталога под SparkFiles.

Первый проход охоты утверждал, что Unix-абсолютный фрагмент игнорирует root (игнорирование родителя в java.io.File для абсолютных дочерних путей). На Unix new File(root, "/abs") отбрасывает ведущий слэш и присоединяется под root. Родитель игнорируется только на Windows. Обход High на этом пине — #../.

Лаборатория

cd lab
./run.sh

Loopback 127.0.0.1:18930. Проект Compose spark-connect-archive-fragment. Образ eclipse-temurin:21-jdk-jammy, uid среды выполнения 1000. Свидетель SPARK-CONNECT-ARCHIVE-FRAGMENT-WITNESS. Последняя строка:

SUCCESS SPARK-CONNECT-ARCHIVE-FRAGMENT how=gadget dest-outside=yes deleteRecursively=yes files-concat=rejected uid=1000 SPARK-CONNECT-ARCHIVE-FRAGMENT-WITNESS
Скачать инструмент