Экранирование значений в SVG в next/og открывает путь к выполнению кода на сервере Next.js

Next.js

В Next.js обнаружили уязвимость критической степени опасности. GitHub отнёс её к критическим по шкале CVSS 4.0. Неаутентифицированный злоумышленник может выполнить на сервере собственный код. Ему не нужна учётная запись, и он не заставляет жертву открывать ссылку. Затронуты приложения, которые собирают картинки для предпросмотра ссылок средствами пакета next/og. Достаточно одного специально составленного сетевого запроса.

Детали уязвимости

Речь идёт о генерации изображений через ImageResponse - компонент, который превращает описание макета в готовую картинку. Чаще всего так делают превью для мессенджеров и социальных сетей: изображение для предпросмотра ссылки, карточку товара, баннер с заголовком статьи. В реализации для Node.js процесс идёт через библиотеку Satori. Она не запускает браузер, а сама разбирает описание на языке разметки и стилей и собирает из него векторный формат SVG, из которого затем получается растровый файл. Пакет next/og работает поверх этой библиотеки.

Сбой кроется в экранировании. Значения, попадающие в готовый SVG, не всегда преобразуются в безопасный текст. Приложение берёт строку из параметра запроса, поля формы, адреса или ответа внешнего интерфейса и вставляет её в содержимое картинки, в атрибут или в стиль. Тогда эта строка может быть разобрана как разметка, а не как подпись. Вредоносная конструкция перестаёт быть безобидным текстом и становится частью документа, который обрабатывает сервер. Отсюда и берётся удалённое выполнение кода. Слабость отнесли к категории зависимости от уязвимого стороннего компонента.

Уязвимость носит идентификатор GHSA-vcvr-r3jv-pc5j. По классификации GitHub она критическая. Атакующий действует по сети, сложность низкая, права ему не нужны, участие пользователя не требуется. Однако в описании указаны и условия атаки, без которых эксплуатация не сработает.

Опасность касается не всех. Уязвимость проявляется при совпадении нескольких условий. Приложение работает на Next.js с 16.2.0 по 16.3.5; генерация картинок идёт через реализацию ImageResponse для Node.js; недоверенные данные попадают в содержимое, атрибуты или стили SVG; маршрут генерации доступен извне. Развёртывания на Edge-реализации ImageResponse проблеме не подвержены. Приложения, которые не вставляют внешние данные в SVG, тоже вне зоны риска.

Разница между Node.js и Edge здесь принципиальна. В Edge-среде код исполняется в изолированной среде выполнения без доступа к файловой системе и системным вызовам, поэтому цепочка атаки обрывается. Node.js таких ограничений не накладывает, и выполненный код получает те же права, что и само приложение.

Маршруты генерации превью почти всегда открыты в интернет. По ним ходят боты социальных сетей и мессенджеров, поэтому проверку подлинности на них обычно не ставят. Картинка часто собирается напрямую из параметров адреса - заголовка страницы, идентификатора записи, имени пользователя. Такая схема и создаёт условия для атаки. Сведений о том, что уязвимость уже используют в реальных атаках, в бюллетене нет. CVE-идентификатор ей пока не присвоен.

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

Исправление уже вышло. Компания Vercel выпустила Next.js 16.3.6, где ошибку закрыли. Для ветки 15.x подготовили 15.5.26 - это укрепляющее обновление, связанное с той же проблемой. После обновления приложение нужно развернуть заново. Библиотеку Satori тоже поправили, исправление вошло в версию 0.33.5.

Satori применяют и вне Next.js - как самостоятельный инструмент для сборки картинок. В таких проектах обновление до 0.33.5 тоже обязательно, даже если Next.js в стеке нет.

Если обновиться немедленно нельзя, разработчикам советуют не передавать недоверенные значения в содержимое, атрибуты и стили SVG, которые отрисовывает реализация ImageResponse для Node.js. Для прямых пользователей Satori полного обходного решения нет. В рекомендациях сказано, что поможет только обновление и отказ от подстановки внешних данных в отрисовываемый контент. Проверить нужно маршруты, формирующие превью, обработчики запросов и динамические генераторы картинок, которые читают значения из запроса. Проверить нужно не только основной пакет: если зависимости фиксируются в конфигурации или собираются в образ контейнера, обновление следует закрепить и там.

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

Ссылки

Комментарии: 0