От имени схемы до RCE: разбор CVE-2026-33696 в n8n
Исследователь безопасности Симон Кёк опубликовал разбор уязвимости CVE-2026-33696 в популярной платформе автоматизации рабочих процессов n8n. Изъян классический — prototype pollution, — но путь от него до полного контроля над сервером получился почти хрестоматийным.
Одна строчка кода
Кёк искал в кодовой базе места, где пользовательская строка попадает в качестве ключа на обычный объект без проверки на опасные имена вроде __proto__, constructor и prototype. Узел GSuiteAdmin бросился в глаза сразу. В нём есть секция «Custom Fields» для создания и обновления пользователей, где имя схемы, имя поля и значение целиком берутся из конфигурации рабочего процесса — то есть полностью контролируются атакующим с правами редактора.
Имя схемы используется как динамический ключ:
customSchemas[schemaName] ??= {};
(customSchemas[schemaName])[fieldName] = value;
Если подставить schemaName равным __proto__, запись уходит прямо в Object.prototype. Вся уязвимость умещается в эти две строки.
От загрязнения к выполнению кода
Само по себе загрязнение уже разрушительно: TypeORM при обходе свойств через for...in начинает натыкаться на лишние поля и бросает ошибку на каждом запросе к базе. Интерфейс n8n зависает, все выполнения падают, и вернуть систему к жизни можно только полным перезапуском.
Но Кёк пошёл дальше и собрал цепочку до RCE. Библиотека simple-git создаёт пустой объект окружения {}, который наследует свойства загрязнённого прототипа. При вызове spawn() Node.js переносит в дочерний процесс и унаследованные свойства. А git, встретив SSH-подобный URL, запускает содержимое переменной GIT_SSH_COMMAND как команду оболочки. Достаточно загрязнить Object.prototype.GIT_SSH_COMMAND — и произвольная команда выполнится от имени процесса n8n.
Полная атака выглядит так: вебхук → узел GSuiteAdmin (загрязнение) → узел Git (выполнение). Один HTTP-запрос запускает всю цепочку. При этом узел GSuiteAdmin падает на обращении к Google API, но это уже неважно — загрязнение происходит до отправки запроса.
Последствия и исправление
Под удар попадают все варианты развёртывания — self-hosted, режим воркеров и облако. Атакующий получает выполнение кода от имени процесса n8n, а значит и доступ к ключу шифрования всех сохранённых учётных данных, плюс возможность устроить полный отказ в обслуживании.
Лечится всё тривиально: достаточно отклонять опасные имена свойств или создавать объект через Object.create(null). Ирония в том, что в кодовой базе n8n уже есть утилита deepMerge с защитой от prototype pollution — узел GSuiteAdmin просто ею не пользовался.
Отчёт был отправлен команде безопасности n8n 26 февраля 2025 года, а публикация advisory и CVE состоялась 25 марта 2025 года.
Источник: Lobsters
Комментарии
Войдите, чтобы комментировать.