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

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

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

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

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

Категории

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

CVE-2026-14361

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

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

Популярное

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

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

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

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

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

CVE-2026-14361

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

Intro

Я нашёл эту проблему при анализе HashiCorp Consul Template, задав прямой вопрос о безопасности файловой системы:

Если writeToFile получает путь, который выглядит находящимся внутри задуманного каталога, проверяет ли он, куда файловая система фактически запишет данные?

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

Помощник шаблона writeToFile открывал итоговый указанный пользователем путь напрямую через os.Create() или os.OpenFile().

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

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

В моём контролируемом proof of concept связанный родительский каталог перенаправил отрисованный вывод за пределы задуманного дерева каталогов и привёл к перезаписи существующего целевого файла.

Эта проблема стала CVE-2026-14361.

Бюллетень HashiCorp: HCSEC-2026-20
Бюллетень IBM: бюллетень безопасности CVE-2026-14361
CVE: CVE-2026-14361
Исправлено в: 0.42.1

photo0


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

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


Что делает writeToFile

Consul Template отрисовывает данные из таких источников, как Consul и Vault.

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

В документации HashiCorp этот помощник специально демонстрируется на материалах PKI:

root@kitploit:~
private key -> writeToFile /my/path/to/cert.key
certificate authority -> writeToFile /my/path/to/cert.pem
certificate -> append to /my/path/to/cert.pem

Это делает его не просто обычным помощником для вывода данных.

Содержимое, пересекающее эту границу, может включать:

  • закрытые ключи
  • сертификаты
  • секреты, полученные из Vault
  • значения конфигурации
  • учётные данные сервисов

Важным вопросом было не то, может ли writeToFile создать запрошенное имя файла.

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

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

В уязвимых версиях он доверял второму.


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

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

Интересные сбои часто не являются классическим обходом через ../.

Это сбои разрешения путей:

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

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

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

Но если он может влиять на компонент пути внутри задуманного каталога записи, более привилегированный процесс Consul Template может выполнить запись за него.

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


Граница, которую я исследовал

Я подошёл к этому не как к обычному анализу обхода путей.

Предоставленному пути не нужны сегменты ...

Он мог всё время оставаться лексически внутри задуманного корневого каталога.

Более сильный вопрос звучал так:

Отвергаются ли связанные компоненты назначения до того, как будет записано чувствительное содержимое?

Этот вопрос важен для двух случаев:

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

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

Файловая система разрешает его в другом месте.


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

Корневая причина — прямое создание файла на основе пути без проверки символических ссылок.

В протестированной ревизии writeToFile() выбирал один из двух путей открытия.

Режим добавления использовал:

root@kitploit:~
f, err = os.OpenFile(
    path,
    os.O_APPEND|os.O_WRONLY|os.O_CREATE,
    perm,
)

Обычный режим записи использовал:

root@kitploit:~
dirPath := filepath.Dir(path)

if _, err := os.Stat(dirPath); err != nil {
    err := os.MkdirAll(dirPath, os.ModePerm)
    if err != nil {
        return "", err
    }
}

f, err = os.Create(path)

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

Это важно, потому что:

  • os.Create(path) следует существующим перенаправлениям файловой системы и усекает разрешённый файл
  • os.OpenFile(path, ...) следует связанным компонентам пути в режиме добавления
  • связанный каталог меняет то, где разрешается конечное имя файла
  • связанный конечный компонент может перенаправить открытие на другой существующий файл

То же предположение, основанное на пути, сохранялось и после записи.

Владелец и права доступа снова применялись через путь:

root@kitploit:~
err = os.Chown(path, uid, gid)
err = os.Chmod(path, perm)

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

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

Потому что атакующий может подготовить перенаправление до запуска writeToFile.

Для базовой атаки не требуется вероятностная гонка.

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

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

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


Почему это проблема безопасности, а не просто обычное поведение символических ссылок

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

Это не делает такое поведение приложения безопасным.

Вопрос безопасности не в том:

«Вёл ли себя Go так, как задокументировано?»

Настоящий вопрос в том:

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

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

Это различие важно, потому что Consul Template может работать:

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

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


Proof of Concept

Я создал автономный воспроизводитель на основе точного поведения writeToFile в протестированном коммите.

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

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

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

  1. Создайте задуманный корневой каталог вывода.
  2. Создайте отдельный внешний целевой каталог.
  3. Разместите существующий целевой файл во внешнем каталоге.
  4. Создайте связанный родительский каталог внутри задуманного корневого каталога, который разрешается во внешний каталог.
  5. Сформируйте конечный путь назначения, используя связанный родительский каталог, оставляя строку пути внутри задуманного корневого каталога.
  6. Вызовите уязвимый путь записи с контролируемым секретным содержимым.
  7. Разрешите и проверьте фактическое место назначения.
  8. Сравните байты конечного файла и SHA-256 с секретным входным содержимым.

Наблюдаемое поведение было таким:

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

Это подтвердило обе части утверждения:

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

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

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

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

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

Существующий целевой файл тоже был важен.

Без него PoC показал бы только неожиданное создание файла.

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

Это сделало результат более конкретным, чем утверждение, основанное только на исходном коде.


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

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

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

Затем процесс 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 and including 0.42.0
Fixed:    consul-template 0.42.1

Исправление вышло в релизе 0.42.1 8 июля 2026 года.


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

Патч 0.42.1 укрепил путь записи на нескольких уровнях.

1. Отклонение связанных компонентов назначения

Исправленный помощник использует os.Lstat() для проверки:

  • непосредственного родительского каталога
  • конечного компонента назначения

и отклоняет эти компоненты, если они являются ссылками.

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

2. Использование O_NOFOLLOW для финального открытия там, где это поддерживается

На поддерживаемых платформах Unix назначение открывается с флагом O_NOFOLLOW.

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

Это важно, потому что одна лишь предварительная проверка может создать ещё одно окно TOCTOU.

Платформенно-зависимая реализация является no-op на Windows, где O_NOFOLLOW недоступен через тот же механизм.

3. Применение метаданных через открытый дескриптор

Патч заменил операции с владельцем и режимом, основанные на пути, операциями на основе дескриптора:

root@kitploit:~
f.Chown(uid, gid)
f.Chmod(perm)

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

4. Безопасный отказ при неожиданных ошибках stat

Теперь помощник создаёт родительский каталог только тогда, когда ошибка stat действительно является os.IsNotExist.

Другие ошибки, такие как сбои прав доступа, возвращаются вместо продолжения по пути записи.

Покрытие регрессионными тестами

Патч добавил целевые тесты для:

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

Важная граница исправления

Публичное обсуждение патча чётко документирует важное ограничение.

Новая проверка проверяет:

  • непосредственный родительский каталог
  • конечный компонент пути

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

Поддерживающие выбрали эту границу, потому что у writeToFile нет настроенного корневого каталога песочницы, к которому можно привязать полную проверку изоляции, а распространённые операционные системы могут включать легитимные управляемые ссылки в префиксы путей, например /var -> /private/var на macOS.

O_NOFOLLOW также защищает конечный компонент, а не каждый родительский каталог.

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

Но это проясняет точное свойство безопасности, обеспечиваемое патчем:

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

Это различие стоит сохранить в техническом описании.


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

Я сообщил об этой проблеме конфиденциально в HashiCorp Security 21 марта 2026 года как о второй независимой находке в Consul Template.

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

  • анализ корневой причины на уровне исходного кода
  • автономный proof of concept
  • вывод во время выполнения
  • доказательства предполагаемого и разрешённого пути
  • поведение файла до и после
  • подтверждение SHA-256 того, что перенаправленный целевой файл совпал с секретным входным содержимым
  • сведения о затронутой ревизии

Первоначальное повторное письмо отсутствовало в очереди отчётов команды безопасности, вероятно, потому что оно было перехвачено спам-фильтром списка рассылки.

После того как я повторно переслал полный отчёт, HashiCorp связался с инженерной командой и исследовал проблему отдельно от первой проблемы Consul Template.

HashiCorp исправил уязвимость в 0.42.1 и опубликовал HCSEC-2026-20 8 июля 2026 года.

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

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

Mohamed Abdelaal (0xmrma)


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

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

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

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

Проверки того, что строка начинается с задуманного каталога, недостаточно.

Даже чистый путь без последовательностей обхода может разрешиться в другом месте через:

  • символические ссылки
  • junction каталогов
  • перенаправления точек монтирования
  • изменяемые компоненты пути

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

Эта проблема также подтверждает более общее правило:

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

Именно поэтому изменения Chown и Chmod на основе дескриптора так важны.


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

  • writeToFile задокументирован для чувствительных материалов, таких как сертификаты и закрытые ключи
  • уязвимые версии открывали место назначения напрямую через os.Create или os.OpenFile
  • связанные родительский и конечный компоненты могли перенаправлять фактическую запись
  • настроенный путь мог оставаться внутри задуманного корневого каталога, в то время как разрешённый целевой файл находился за его пределами
  • обычный режим создания мог усекать и перезаписывать существующий целевой файл
  • основанные на пути Chown и Chmod вносили дополнительное доверие к изменяемому пути
  • PoC доказал перенаправление и перезапись с помощью побайтового сравнения SHA-256
  • версия 0.42.1 добавила проверки ссылок, O_NOFOLLOW там, где это поддерживается, операции с метаданными на основе дескриптора и регрессионные тесты

Заключение

Эта уязвимость не была связана с обходом через ../.

Строка пути выглядела корректно.

Место назначения в файловой системе — нет.

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

Именно поэтому это стало CVE-2026-14361.

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

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