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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-5061 — Consul Template проверял, куда указывала символическая ссылка во время оценки шаблона, но при последующем получении зависимостей читал исходный путь. Перенаправление ссылки между этими операциями превращало ссылку на файл внутри песочницы в раскрытие файла за её пределами. | Kitploit
Инструменты/GitHubGitHub/0xmrma/cve-2026-5061
Анализ уязвимостейАнализ КодаЭксплуатацияЭксфильтрация данныхОбучение и Образование
GitHub0xmrma/cve-2026-5061

CVE-2026-5061

Consul Template проверял, куда указывала символическая ссылка во время оценки шаблона, но при последующем получении зависимостей читал исходный путь. Перенаправление ссылки между этими операциями превращало ссылку на файл внутри песочницы в раскрытие файла за её пределами.

Репозиторий
131 месяц назадЕщё не проверено

Популярное

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

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

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

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

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

CVE-2026-5061

Consul Template проверял, куда указывает символическая ссылка во время вычисления шаблона, но последующее получение зависимости читало исходный путь. Перенацеливание ссылки между этими операциями превращало ссылку на файл внутри песочницы в раскрытие файла за её пределами.

Введение

Я обнаружил эту проблему при изучении HashiCorp Consul Template, задаваясь вполне конкретным вопросом безопасности:

Если sandbox_path проверяет символическую ссылку во время вычисления шаблона, остаётся ли последующее чтение файла привязанным к той же проверенной цели?

В данном случае ответ был отрицательным.

Хелпер шаблона file разрешал путь и обеспечивал соблюдение настроенной песочницы во время вычисления шаблона. Но после этой проверки он создавал файловую зависимость, используя исходный «сырой» путь.

Эта зависимость получалась позже.

Если атакующий перенацеливал символическую ссылку в промежутке между проверкой и получением зависимости, Consul Template мог прочитать файл за пределами песочницы. Если ссылка восстанавливалась до следующего рендеринга, проверка песочницы снова проходила успешно, а кэшированное внешнее содержимое всё равно попадало в вывод.

Эта проблема получила номер CVE-2026-5061.

Бюллетень HashiCorp: HCSEC-2026-12
Бюллетень IBM: бюллетень безопасности CVE-2026-5061


CVE:
CVE-2026-5061

Исправлено в:
0.42.0

photo0


Цепочка атаки

attacker-controlled in-sandbox symlink -> sandbox validation resolves to safe target -> dependency stores original raw path -> attacker retargets link outside sandbox -> dependency fetch reads external file -> attacker restores safe link -> next validation passes -> cached external content is rendered


Что делает Consul Template

Consul Template — это инструмент рендеринга шаблонов для данных из Consul и Vault.

Он может работать непрерывно, отслеживать изменения зависимостей и выводить данные в файлы или переменные окружения для использования приложениями.

Хелпер шаблона file читает локальный файл и вставляет его содержимое в отрендеренный вывод.

Поскольку чтение локальных файлов может раскрывать секреты, доступные процессу, Consul Template предоставляет sandbox_path в качестве границы для этого хелпера.

Документированное свойство безопасности простое:

  • пути, передаваемые в file, должны находиться внутри настроенной песочницы
  • относительные пути не должны выходить за пределы песочницы
  • цели символических ссылок не должны превращать разрешённый путь в чтение внешнего файла

Это делает sandbox_path реальной границей безопасности.

Важным был не вопрос о том, выглядел ли путь так, будто он находится внутри песочницы.

Настоящий вопрос заключался в следующем:

Остаётся ли читаемый файл тем же самым файлом, который прошёл проверку песочницы?

В уязвимых версиях — нет.


Почему эта поверхность атаки заслуживала внимания

Файловые песочницы часто ломаются именно в промежутке между проверкой пути и доступом к файлу.

Типичный сценарий таков:

  • проверить путь
  • вернуть управление файловой системе
  • использовать путь позже снова
  • предположить, что он по-прежнему указывает на тот же объект

Это предположение небезопасно, если атакующий может изменить символическую ссылку или аналогичное перенаправление файловой системы между двумя операциями.

Consul Template делал эту поверхность атаки особенно интересной, потому что вычисление шаблона и получение зависимостей были отдельными этапами.

Это разделение породило правильный вопрос безопасности:

Привязано ли получение зависимости к проверенной цели, или оно снова разрешает путь, контролируемый атакующим?

Именно эту границу я исследовал.


Корневая причина

Корневая причина заключалась в несоответствии типа time-of-check to time-of-use (TOCTOU) между:

  • проверкой песочницы в template/funcs.go
  • последующим чтением зависимости в dependency/file.go

В протестированной ревизии fileFunc() делала следующее:

root@kitploit:~
normalized := strings.TrimSpace(s)
err := pathInSandbox(sandboxPath, normalized)
if err != nil {
    return "", err
}

d, err := dep.NewFileQuery(s)

Хелпер проверки корректно разрешал символические ссылки перед проверкой нахождения в песочнице:

root@kitploit:~
sandboxResolved, err := filepath.EvalSymlinks(filepath.Clean(sandbox))
targetResolved, err := filepath.EvalSymlinks(filepath.Clean(path))

rel, err := filepath.Rel(sandboxResolved, targetResolved)
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
    return fmt.Errorf("'%s' is outside of sandbox", path)
}

Итак, сама проверка песочницы учитывала разрешённую цель.

Но эта разрешённая цель отбрасывалась.

NewFileQuery() вместо неё сохраняла исходную строку:

root@kitploit:~
return &FileQuery{
    stopCh: make(chan struct{}, 1),
    path:   s,
}, nil

Затем последующее получение зависимости снова читало этот путь:

root@kitploit:~
data, err := os.ReadFile(d.path)

В этом и заключается вся уязвимость.

Код проверял один результат разрешения пути в файловой системе, а затем использовал другой.

Почему это эксплуатируемо

Потому что символическая ссылка изменяема.

Атакующему не нужно, чтобы цель за пределами песочницы напрямую проходила pathInSandbox().

Им нужно лишь изменить то, на что уже одобренный «сырой» путь указывает после проверки, но до того, как Fetch() выполнит чтение.

Последовательность такова:

  • ссылка указывает на безопасный файл во время pathInSandbox()
  • проверка проходит успешно
  • FileQuery сохраняет «сырой» путь ссылки
  • ссылка заменяется или перенацеливается на внешний файл
  • os.ReadFile(d.path) снова разрешает ссылку
  • внешний файл читается
  • полученное значение кэшируется в «мозге» шаблона
  • ссылка восстанавливается до следующего вычисления шаблона
  • проверка снова проходит успешно
  • кэшированное внешнее содержимое возвращается и попадает в вывод

Последний шаг важен.

Восстановление безопасной ссылки не удаляло уже полученный секрет из кэша зависимостей.


Почему это проблема безопасности, а не просто гонка в файловой системе

Ключевое отличие — обход явного механизма безопасности.

Это было не просто:

«файл изменился, пока Consul Template наблюдал за ним»

Наблюдение за файлами на предмет изменений — ожидаемое поведение.

Настоящая проблема заключалась в следующем:

путь, прошедший документированное ограничение песочницы, впоследствии мог быть использован для чтения файла за пределами этой песочницы

Это прямой отказ границы доверия.

Приложение уже приняло решение о безопасности:

  • эта цель находится внутри песочницы
  • следовательно, её безопасно регистрировать и получать

Но последующее получение не было привязано к той цели, которая обосновала это решение.

Именно это превратило обычную изменчивость файловой системы в уязвимость.


Доказательство концепции (PoC)

Я собрал автономный воспроизводитель вокруг точной последовательности «вычисление шаблона → получение зависимости».

В контролируемой настройке использовались:

  • настроенный каталог песочницы
  • безопасный файл внутри этой песочницы
  • секретный файл за пределами песочницы
  • отслеживаемый путь символической ссылки внутри песочницы
  • детерминированные переключения ссылки в момент получения зависимости

Процесс воспроизведения был таким:

  1. Направить отслеживаемую символическую ссылку на безопасный файл внутри песочницы.
  2. Вычислить хелпер file, чтобы проверка песочницы прошла успешно и «сырой» путь был зарегистрирован как зависимость.
  3. Перенацелить отслеживаемую символическую ссылку на внешний секрет до получения зависимости.
  4. Выполнить получение зависимости и позволить os.ReadFile(d.path) прочитать данные через перенаправленную ссылку.
  5. Сохранить полученное значение в кэше шаблона.
  6. Восстановить символическую ссылку на безопасный файл внутри песочницы.
  7. Вычислить шаблон снова.
  8. Подтвердить, что проверка песочницы по-прежнему проходит успешно.
  9. Подтвердить, что отрендеренный вывод содержит ранее полученный внешний секрет.

Наблюдаемое поведение было следующим:

  • первоначальная проверка песочницы прошла успешно
  • зависимость сохранила исходный путь ссылки
  • получение прочитало файл за пределами песочницы после изменения ссылки
  • безопасная цель была восстановлена до следующего рендеринга
  • следующая проверка песочницы прошла успешно
  • отрендеренный вывод точно совпал с внешним секретом по SHA-256

Это сравнение хэшей имело значение.

Оно доказало, что итоговое отрендеренное значение — это не устаревшее безопасное содержимое, не артефакт имени файла и не побочный эффект пути обработки ошибок.

Это было побайтово точное содержимое файла за пределами песочницы.


Почему PoC был выбран именно так

Самое убедительное доказательство проблемы TOCTOU должно контролировать временную последовательность.

Простая демонстрация того, что символическая ссылка может указывать за пределы песочницы, была бы слабее, поскольку pathInSandbox() и так отклоняет внешнюю цель, когда обнаруживает её.

Утверждение о безопасности зависело от доказательства всех этих состояний по порядку:

  • безопасно в момент проверки
  • небезопасно в момент получения
  • снова безопасно в момент рендеринга
  • внешнее содержимое по-прежнему берётся из кэша

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

PoC не полагался на случайные тайминги и многократные угадывания.

Он детерминированно проходил уязвимый жизненный цикл.

Это сделало корневую причину и последствия гораздо легче обосновать.


Требования к эксплуатации и область применения

Эта проблема требует возможности влиять на локальную файловую систему.

Атакующему нужен достаточный уровень доступа, чтобы создать, заменить или перенацелить соответствующую символическую ссылку или аналогичный связанный путь в течение уязвимого окна.

Процесс Consul Template также должен:

  • иметь разрешение на чтение внешней цели
  • вычислять шаблон с использованием пути, на который влияет атакующий
  • выводить результат рендеринга туда, где атакующий может его получить или повлиять на его использование

Эти требования важны.

Это не было неаутентифицированным удалённым чтением произвольных файлов в конфигурации по умолчанию.

Но в рамках затронутой локальной модели доверия последствия были существенными:

  • обход документированного ограничения sandbox_path
  • раскрытие локальных файлов за пределами песочницы
  • возможное раскрытие секретов, доступных для чтения процессом Consul Template

Риск возрастает, когда процесс работает с доступом к чувствительным учётным данным, конфигурации сервисов, токенам или закрытым ключам.


Серьёзность и классификация

HashiCorp классифицировал проблему как:

  • CWE-59: некорректное разрешение ссылки перед доступом к файлу
  • CVSS 3.1:
root@kitploit:~
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N

Опубликованная базовая оценка:

root@kitploit:~
4.7 / Medium

Эта оценка отражает реальные ограничения:

  • локальный вектор атаки
  • низкие привилегии, требуемые для влияния на путь
  • высокая сложность атаки, поскольку ссылка должна измениться в течение соответствующего окна жизненного цикла
  • отсутствие необходимости взаимодействия с жертвой
  • высокое влияние на конфиденциальность, если получен чувствительный файл, доступный процессу

Это разумная классификация.

Проблема узка по предъявляемым к атакующему требованиям, но обход песочницы и результирующее раскрытие файлов — вполне конкретны.


Затронутые версии

В бюллетене HashiCorp указано:

root@kitploit:~
Affected: consul-template up to 0.41.4
Fixed:    consul-template 0.42.0

Исправление вышло в релизе 0.42.0 15 апреля 2026 года.


Анализ исправления

Исправление небольшое и напрямую устраняет нарушенную привязку.

Вместо проверки разрешённой цели и последующего создания зависимости из исходных данных исправленный код возвращает разрешённый путь и передаёт его в NewFileQuery():

root@kitploit:~
resolvedPath, err := resolveSandboxedPath(
    sandboxPath,
    strings.TrimSpace(s),
)
if err != nil {
    return "", err
}

d, err := dep.NewFileQuery(resolvedPath)

Свойство безопасности изменилось с:

  • проверять разрешённую цель
  • отбрасывать разрешённую цель
  • получать данные позже через «сырой» путь

на:

  • проверять разрешённую цель
  • сохранять разрешённую цель
  • получать данные через проверенный путь

Это закрывает описанный вектор перенацеливания символической ссылки, потому что изменение исходной ссылки больше не меняет путь, сохранённый зависимостью.

Патч также добавил целенаправленный регрессионный тест, покрывающий точную последовательность:

  • безопасная символическая ссылка во время проверки
  • внешняя символическая ссылка во время получения
  • безопасная ссылка, восстановленная перед следующим вызовом
  • кэшированный внешний секрет не должен возвращаться

Это именно та мера устранения, которая нужна для такого бага:

  • исправить нарушенную привязку «проверка/использование»
  • сохранить поведение песочницы
  • добавить регрессионный тест для полного жизненного цикла гонки

Раскрытие информации

Я сообщил об этой проблеме в частном порядке в HashiCorp Security 20 марта 2026 года.

Отчёт включал:

  • анализ корневой причины на уровне исходного кода
  • последовательность TOCTOU «проверка → получение»
  • автономный детерминированный воспроизводитель
  • вывод времени выполнения
  • доказательство по SHA-256, что отрендеренные данные совпали с внешним секретом
  • сведения о затронутой ревизии

HashiCorp исправил проблему в 0.42.0 и опубликовал HCSEC-2026-12 12 мая 2026 года.

IBM опубликовала соответствующий бюллетень безопасности для того же CVE.

Оба официальных бюллетеня указали автора отчёта:

Mohamed Abdelaal (0xmrma)


Чему на самом деле учит этот баг

Ключевой урок прост:

проверки пути недостаточно, если последующая файловая операция может разрешить этот путь в другой объект

Это правило применимо далеко за пределами Consul Template.

Оно важно везде, где код выполняет:

  • проверки песочницы
  • проверки места назначения загрузки
  • извлечение архивов
  • чтение локальных секретов
  • обработку временных файлов
  • файловые операции с разделением привилегий

Более глубокая суть безопасности не в том:

«строка пути однажды выглядела безопасной»

а в том:

объект, используемый чувствительной операцией, должен быть тем объектом, который прошёл проверку

В данном случае Consul Template проверил одно разрешение пути, а получил другое.

Этого разрыва оказалось достаточно.


Ключевые моменты

  • sandbox_path был явной границей безопасности для локальных файлов
  • pathInSandbox() корректно разрешала и проверяла цель символической ссылки
  • разрешённая цель отбрасывалась после проверки
  • FileQuery сохраняла исходный путь, на который влияет атакующий
  • последующее получение зависимости снова разрешало этот путь через os.ReadFile
  • восстановление безопасной ссылки не удаляло уже кэшированное внешнее содержимое
  • PoC доказал побайтовое раскрытие за пределами песочницы с помощью SHA-256
  • версия 0.42.0 исправила баг, привязав зависимость к разрешённому, проверенному пути

Заключение

Эта уязвимость не связана с обходом проверки строкового префикса.

Она связана со временем и идентичностью.

Consul Template проверял, куда указывала ссылка во время вычисления шаблона. Получение зависимости позже снова задало файловой системе тот же вопрос. Атакующий мог изменить ответ между этими двумя моментами.

Именно поэтому проблема получила номер CVE-2026-5061.

Исправлено в consul-template 0.42.0.

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