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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-34070 — Я нашёл уязвимость нулевого дня в langchain — вот как всё прошло | Kitploit
Инструменты/GitHubGitHub/rickidevs/cve-2026-34070
Анализ уязвимостейЭксплуатацияВеб-безопасностьСтатьи и ИсследованияОбучение и Образование
GitHubrickidevs/cve-2026-34070

CVE-2026-34070

Я нашёл уязвимость нулевого дня в langchain — вот как всё прошло

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

Популярное

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

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

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

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

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

Я нашёл уязвимость обхода пути в LangChain, которая может раскрыть ваши облачные учётные данные

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


Есть такое чувство, когда proof-of-concept срабатывает с первой попытки. Не совсем волнение — скорее медленное, неприятное осознание того, что произошло что-то реальное. Именно это я почувствовал, когда запустил свою тестовую конфигурацию против load_prompt_from_config() и увидел, как содержимое файла, который она не имела права читать, выводится прямо в мой терминал.

Это история CVE-2026-34070: уязвимость обхода пути в langchain-core, исправленная в версии 1.2.22.


Почему LangChain?

Если вы создавали что-либо с ИИ за последние пару лет, вы почти наверняка сталкивались с LangChain. Это соединительная ткань современного стека ИИ — фреймворк, который связывает языковые модели, векторные хранилища, инструменты и управление промптами в целостные приложения. С более чем 130k звёзд на GitHub и внедрением во всём — от небольших проектов выходного дня до корпоративных развёртываний — уязвимость здесь не остаётся изолированной.

Я проводил ревизию кода подсистемы промптов, когда мне бросилось в глаза: модуль под названием langchain_core/prompts/loading.py. Он загружал файлы с диска на основе значений, взятых напрямую из десериализованных словарей конфигурации. Без валидации. Без санитизации путей. Просто .

open(path)

Я продолжил читать.


Уязвимый код

В центре этого находились три внутренние функции:

  • _load_template() — читает файлы, на которые ссылаются template_path, suffix_path и prefix_path
  • _load_examples() — читает файлы, на которые ссылается ключ examples, когда он является строкой
  • _load_few_shot_prompt() — читает файлы, на которые ссылается example_prompt_path

Проверки расширений файлов были на месте. .txt для шаблонов. .json, .yaml, .yml для примеров. Но ничто не мешало этим путям быть абсолютными (/etc/passwd) или основанными на обходе (../../../../home/user/.ssh/). Фильтр расширений давал ложное чувство безопасности — он просто означал, что атакующему нужно выбрать правильное расширение, а не то, что атака заблокирована.

Все эти функции доступны через два публичных API: load_prompt() и load_prompt_from_config().


Proof of Concept

Самая простая версия выглядела так:

root@kitploit:~
from langchain_core.prompts.loading import load_prompt_from_config

config = {
    "_type": "prompt",
    "template_path": "/tmp/secret.txt",
    "input_variables": [],
}

prompt = load_prompt_from_config(config)
print(prompt.template)  # содержимое /tmp/secret.txt, выведено чисто

Вот и всё. Передайте абсолютный путь — получите содержимое файла, обёрнутое в PromptTemplate. Без аутентификации. Без особых привилегий. Если вы можете влиять на словарь конфигурации, вы можете читать файлы.

Обход каталогов работал так же чисто:

root@kitploit:~
config = {
    "_type": "prompt",
    "template_path": "../../etc/secret.txt",
    "input_variables": [],
}

Вариант с JSON/YAML был, пожалуй, более опасным из-за типов файлов, к которым он мог получить доступ:

root@kitploit:~
config = {
    "_type": "few_shot",
    "examples": "../../../../.docker/config.json",
    "example_prompt": {
        "_type": "prompt",
        "input_variables": ["input", "output"],
        "template": "{input}: {output}",
    },
    "prefix": "",
    "suffix": "{query}",
    "input_variables": ["query"],
}

prompt = load_prompt_from_config(config)

.docker/config.json содержит ваши учётные данные Docker Hub. ~/.azure/accessTokens.json содержит ваши токены Azure. Манифесты Kubernetes, конфигурации CI/CD, внутренние настройки приложений — любой файл с правильным расширением, находящийся где угодно в файловой системе, был доступен.


Реальная поверхность атаки в реальном мире

Оценка CVSS составила 7.5 High с вектором AV:N/AC:L/PR:N/UI:N — доступный по сети, низкая сложность, без привилегий, без необходимости взаимодействия с пользователем.

Оценка ограничена ниже 9+, потому что проверка расширений файлов действительно ограничивает, какие файлы можно прочитать. Но 7.5 всё равно занижает реальное влияние в определённых моделях развёртывания.

Подумайте, где это приземляется в продакшене:

  • Low-code конструкторы ИИ, которые позволяют пользователям настраивать промпты через интерфейс — если бэкенд передаёт управляемые пользователем конфигурации напрямую в load_prompt_from_config(), каждый пользователь — потенциальный атакующий.
  • API-обёртки, которые предоставляют конечные точки загрузки промптов, предполагая, что библиотека обрабатывает санитизацию.
  • Облачные приложения, где секреты окружения смонтированы как файлы (очень распространённый паттерн на Kubernetes, AWS ECS и GCP).

В таких средах ограничение «расширением файла» имеет гораздо меньшее значение. Атакующий может просто нацелиться на файлы, о существовании которых он знает, с правильным расширением. На типичном облачном экземпляре: requirements.txt, config.yaml, .env.yaml, смонтированные секретные файлы с расширением .json — список длинный.


Почему это существовало в первую очередь

Затронутые функции описаны в бюллетене как «недокументированные устаревшие API». Они предшествуют текущей системе сериализации langchain_core.load (dumpd/dumps/load/loads), которая использует модель на основе белого списка и не выполняет чтение файловой системы.

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

Это паттерн, на который стоит обратить внимание. В быстро развивающихся проектах с открытым исходным кодом, особенно в тех, которые росли так же быстро, как LangChain, технический долг накапливается в углах. Устаревший код, который «никогда не предназначался для пользователей», не получает такого же внимания, как основная поверхность API. Но он всё ещё вызываемый. Он всё ещё в пакете. И если он читает файлы с диска, это потенциальная уязвимость.


Исправление

Патч вышел в langchain-core 1.2.22. Исправление добавляет валидацию путей, которая отклоняет как абсолютные пути, так и последовательности обхода .. до открытия любого файла. Запасной выход — allow_dangerous_paths=True — доступен для приложений, которым действительно нужно читать из доверенных путей, с явным признанием того, что вызывающий код сознательно идёт на риск.

Устаревшие API также официально объявлены устаревшими в этом выпуске. Они будут полностью удалены в 2.0.0. Если вы используете load_prompt() или load_prompt_from_config() где-либо, мигрируйте на эквиваленты langchain_core.load сейчас, а не ждите ломающего изменения.

Обновитесь немедленно:

root@kitploit:~
pip install --upgrade langchain-core

Проверьте, что у вас версия 1.2.22 или новее:

root@kitploit:~
python -c "import langchain_core; print(langchain_core.__version__)"

Что проверить в вашей собственной кодовой базе

Если вы строите на LangChain, стоит провести быстрый аудит:

  1. Найдите load_prompt и load_prompt_from_config в вашей кодовой базе. Если они встречаются, проверьте, что в них передаётся.
  2. Спросите себя, содержат ли какие-либо словари конфигурации, попадающие в эти функции, значения, на которые влияет пользователь. Если ответ «да», вы потенциально были уязвимы до обновления.
  3. Просмотрите структуру файлов вашего развёртывания. Поймите, какие файлы с расширениями .txt, .json или .yaml существуют на ваших экземплярах и что они содержат.

Заключительная мысль

Уязвимости безопасности в ИИ-инфраструктуре будут иметь всё большее значение, а не меньшее, по мере того как эти системы обрабатывают более чувствительные рабочие нагрузки. Команда LangChain отреагировала хорошо — исправление чистое, путь устаревания ясен, а документация бюллетеня тщательная.

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

Читайте код. Особенно старые части.


CVE-2026-34070 была присвоена этой уязвимости. Полный бюллетень доступен в LangChain GitHub Security Advisory.

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