Привет, Хабр! Меня зовут Артем Чувикин, я технический аккаунт‑менеджер в NGENIX и не так давно я выступал в рамках OWASP Security meetup с докладом про риски безопасности, которые появляются при использовании серверного и серверных компонент. Разбирал подробнее недавнюю уязвимость react2shell и меры митигации, которые предлагались для этой уязвимости. 

Сама статья — саммари моего выступления на OWASP Russia Meetup 2026. Я расскажу об основных подходах к рендерингу в современных React‑приложениях, о рисках безопасности при переносе логики на сервер, а также о критической уязвимости react2shell, затронувшей экосистему React Server Components.

В этой статье риски и угрозы будут рассмотрены на примере next.js — ведущим фреймворком в области ssr и в особенности инструментом, который позволяет использовать rsс. Сам доклад я поделил на несколько частей:

  1. Особенность фулл‑стек фреймворков на примере next.js. Верхнеуровнево пройдемся по технологиям, которые там используются.

  2. Рассмотрим недавнюю уязвимость в этом фреймворке — ract2shell. 

  3. И также я хотел рассмотреть меры защиты, которые мне удалось найти и протестировать.

Преимущественно это касается рекомендаций по защите на WAF.

Если ещё несколько лет назад основным подходом был клиентский рендеринг в SPA, то сегодня многие проекты на React и Next.js используют Server‑Side Rendering (SSR), React Server Components (RSC) и Server Actions. Это позволяет ускорить загрузку страниц, улучшить SEO‑показатели и снизить нагрузку на браузер пользователя.
Однако вместе с преимуществами появляются и новые риски. Чем больше логики выполняется на сервере, тем шире становится поверхность атаки. Кроме привычных для веб‑приложений XSS, SSRF или инъекций возникают специфические угрозы, связанные с особенностями работы React Server Components, Flight Protocol и Server Actions.

Фуллстек сервер на next.js 

React уже давно занимает позицию лидера среди библиотек для создания пользовательских интерфейсов. Но для построения полноценного, оптимизированного приложения одного React часто недостаточно. Здесь мы обращаемся к react‑фреймворкам, которые дают дополнительные возможности работы с экосистемой реакт. Одним из таких фреймворков является продукт компании Vercel — Next.js. Де‑факто он стал стандартом для серверного рендеринга и генерации статических сайтов на React. Да и сама команда react рекомендует ипользовать его чуть ли ни как официальную легитимную версию фуллстек фреймворка для своего продукта.

Но чего мы лишаемся, если подобные фреймворки не использовать?
Еще недавно типичное React‑приложение было в первую очередь клиентским: сервер отдавал HTML‑оболочку и JavaScript‑бандл, а браузер уже сам запрашивал данные, строил интерфейс и управлял состоянием. Такой подход прост для фронтенд‑команд, но плохо подходит для SEO, медленного интернета и слабых устройств: до интерактивности пользователь часто ждёт загрузки и выполнения большого объёма JavaScript.

Next.js и похожие фреймворки изменили баланс. Они дают несколько вариантов рендеринга и работы с компонентами. С точки зрения продукта это удобно: можно быстрее показать первый экран, заранее подготовить статические страницы, скрыть часть логики на сервере и уменьшить клиентский бандл. С точки зрения безопасности это означает, что граница между «фронтендом» и «бэкендом» становится менее очевидной.

Главный вывод простой: когда фреймворк становится full‑stack‑платформой, он приносит в приложение не только удобство, но и собственную серверную поверхность атаки. Даже если разработчик не писал отдельный REST‑эндпоинт, приложение может иметь какие внутренние обработчики, которые работают под капотом и про которые мы вообще можем не знать. Это создает определенные скрытые угрозы.

Сравнение вариантов рендеринга 

Next.js дает возможность совмещать в своем проекте несколько вариантов редеринга (работа с серверными компонентами не совсем рендеринг, но сюда тоже добавлю), давайте остановмся на каждом подробнее:

Server‑Side Rendering (SSR)

Классический Server‑Side Rendering предполагает, что пользователь отправляет запрос на сервер, сервер выполняет необходимую бизнес‑логику, получает данные, формирует готовую HTML‑страницу и возвращает её клиенту. Браузеру остаётся только отобразить полученный HTML.

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

Static Site Generation (SSG)

При использовании Static Site Generation страница формируется заранее, ещё на этапе сборки приложения. В момент обращения пользователя серверу не требуется выполнять дополнительную логику — он просто отдаёт уже готовый HTML‑файл.

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

Client‑Side Rendering (CSR)

При клиентском рендеринге сервер отдаёт браузеру минимальную HTML‑страницу и JavaScript‑бандл приложения. После загрузки JavaScript вся логика начинает выполняться непосредственно в браузере пользователя: загружаются данные, строится DOM, обрабатываются пользовательские действия, выполняются API‑запросы.

Такой подход позволяет создавать высокоинтерактивные интерфейсы, однако имеет и недостатки. Например, увеличивается время полной загрузки страницы и возрастает объём JavaScript. К проблемам можно отнести еще ухудшение SEO без дополнительных механизмов индексации.

React Server Components (RSC)

React Server Components появились, как попытка объединить преимущества серверного и клиентского подходов. Идея заключается в том, что часть компонентов может выполняться исключительно на сервере и никогда не попадать в браузер пользователя в виде JavaScript‑кода.

В результате уменьшается объём клиентского JavaScript, снижается нагрузка на браузер, ускоряется загрузка страниц, сохраняются преимущества SEO. При этом интерактивные элементы продолжают работать через клиентские компоненты. Фактически дерево компонентов начинает состоять из комбинации серверных и клиентских частей, каждая из которых выполняется в своей среде.

Отличается и время отображения страницы. При CSR сервер быстро отдаёт HTML‑заглушку, однако пользователь вынужден ждать загрузки JavaScript. В SSR сервер сначала формирует страницу, а затем отправляет её клиенту. В RSC дополнительно используются механизмы потоковой передачи данных, что позволяет быстрее отображать контент. С точки зрения SEO серверные подходы традиционно выглядят предпочтительнее, поскольку поисковые роботы получают уже подготовленный контент.

Варианты рендеринга приложений
Варианты рендеринга приложений

Page router и App router 

Теперь про то как реализуется возможность работы с различными вариантами рендеринга в next.js.

Исторически в Next.js использовался механизм Page Router. В этой модели разработчик мог комбинировать несколько вариантов рендеринга: SSG, SSR и CSR. Pages Router строится вокруг директории pages. Файл pages/about.tsx автоматически становится маршрутом /about, pages/blog/[id].tsx — динамическим маршрутом, а pages/api/*.ts — API Routes. Эта модель долго была основной для Next.js и остается поддерживаемой, но официальная документация рекомендует App Router для новых возможностей React.

Page Router
Page Router

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

Позже появился App Router и стал логическим развитием существующей архитектуры. Главным отличием стало появление React Server Components и Server Actions.Теперь сервер может не только формировать HTML, но и участвовать непосредственно в обработке отдельных компонентов приложения.

Логика App Router строится вокруг директории app. Маршрут описывается папками, а UI создают специальные файлы page.tsx, layout.tsx, loading.tsx, error.tsx, not‑found.tsx. В этой модели Server Components используются по умолчанию, а клиентский код явно помечается директивой use client.

App Router
App Router

При запросе страницы сервер формирует специальный RSC Payload, который используется для построения итогового дерева компонентов. После получения данных клиент согласует своё дерево компонентов с серверным представлением и делает страницу интерактивной. Дополнительно появляются Server Actions — механизм удалённого вызова серверных функций непосредственно из интерфейса приложения. Именно эти возможности существенно меняют модель угроз современных React‑приложений.

Фичи, которые мы получили в app router

RSC

React Server Components меняют привычную модель. Серверный компонент выполняется на сервере и не отправляет свой код в браузер. Он может обращаться к базе данных, файловой системе или внутренним сервисам, а клиент получает сериализованное представление результата и ссылки на клиентские компоненты, которые нужно гидрировать. В App Router Next.js серверные компоненты стали поведением по умолчанию: клиентским компонент становится только после директивы use client.

import LikeButton from './LikeButton'
import { getPost } from '@/lib/data'

export default async function Page({ params }) {
  const post = await getPost(params.id) // выполняется на сервере

  return (
    <main>
      <h1>{post.title}</h1>
      <LikeButton likes={post.likes} />
    </main>
  )
}

Server Actions

Server Actions позволяют вызывать серверные функции из UI‑кода, например из HTML‑формы. Разработчику не нужно вручную создавать API‑маршрут для каждой мутации. Но с точки зрения безопасности Server Action остается удаленно вызываемой серверной операцией. Нельзя полагаться на то, что она «спрятана» внутри компонента или недоступна без JavaScript: для атакующего это все равно сетевой интерфейс.

// app/actions.ts
'use server'

import { z } from 'zod'
import { getCurrentUser, assertCanCreateItem } from '@/lib/auth'
import { createItem } from '@/lib/db'

const schema = z.object({
  name: z.string().min(1).max(80),
})

export async function addItem(formData: FormData) {
  const user = await getCurrentUser()
  if (!user) throw new Error('Unauthorized')

  const input = schema.parse({
    name: formData.get('name'),
  })

  await assertCanCreateItem(user)
  await createItem({ ownerId: user.id, name: input.name })
}

Flight протокол 

Для склеивания работы клиента и сервера при использовании RSC, Serer Actions используется конечно все тот же html, а если быть точнее JSON формат. Но это не обычный JSON, а специальная нотификация — Flight. Благодаря fligut сервер и клиент могут общаться в потоковом формате, обмениваясь данными, в которых описаны результаты обработки серверных компонентов, ссылки на клиентские компоненты, значения props, промисы и другие структуры, нужные для восстановления дерева на клиенте и для вызова выше упомянутых server actions. В Next.js этот слой скрыт от нас как от разработчиков. Более того, даже нормальной и официальной документации о том как все это работает — нет. Поэтому пришлось по кусочкам собирать информацию о том как все это работает и параллельно тестировать, перехватывая запросы и ответы приложения. 

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

Как представляются данные по flight формату
Как представляются данные по flight формату

Структура чанков

Внутри Flight Protocol данные передаются в виде чанков (chunks). Каждый чанк представляет собой отдельный объект данных. У каждого объекта есть собственный идентификатор, а также возможность ссылаться на другие объекты.

Структура чанков
Структура чанков

Упрощённо структуру можно представить следующим образом:

Chunk 0 
└── ссылка на Chunk 1

Chunk 1 
└── содержит объект данных

Chunk 2 
└── ссылка на Chunk 0 через Promise

В результате на стороне клиента или сервера из отдельных чанков восстанавливается полноценный граф объектов. Такая схема обеспечивает высокую гибкость передачи данных, но одновременно повышает сложность обработки.
Появляются ссылки между объектами, отложенные значения, промисы и механизмы восстановления зависимостей. Чем сложнее логика восстановления данных, тем больше вероятность появления ошибок реализации. Именно особенности обработки таких чанков сыграли ключевую роль в появлении уязвимости react2shell, но об этом чуть позже.

Какие риски появляются при переносе логики на сервер

Сам факт использования SSR или React Server Components не делает приложение небезопасным.Проблема заключается в другом: сервер начинает выполнять значительно больший объём логики и получает доступ к данным, которые раньше не покидали внутренний контур приложения. Соответственно, расширяется и поверхность атаки.

Теперь, после небольшого экскурса по видам рендеринга и фишкам next.js, наконец можно переходить рискам. Среди наиболее распространённых рисков можно выделить:

1. XSS

Уязвимости межсайтового выполнения сценариев никуда не исчезают при переходе к SSR. Более того, при серверном рендеринге важно отдельно контролировать настройки Content Security Policy (CSP), поскольку механизмы защиты могут работать иначе, чем в полностью клиентских приложениях.

Если говорить о конкретных уязвимостях, то тут можно рассмотреть несколько конкретных примеров: 

  • CVE-2026-44580 — XSS через beforeInteractive скрипты
    Тут сериализованное содержимое скриптов, загружаемых через beforeInteractive, не экранировалось должным образом перед вставкой в документ. Если использовать beforeInteractive скрипты с непроверенным пользовательским контентом, то атакующий может внедрить управляющие символы, которые «вырывают» его код из контекста данных. В отличие от классического XSS тут уязвим не код приложения, а стандартный механизм самого фреймворка по работе со скриптами. 

  • CVE-2025-13984: XSS через кросс‑доменную политику
    Уязвимость в Drupal Next.Js, связанная с недостаточной безопасностью в политике для кросс‑доменных запросов, что позволяло выполнить XSS‑атаку.

  • CVE-2026-26993: Stored XSS через загрузку SVG
    Уязвимость в приложении, основанном на Next.js позволяла загружать SVG‑файлы с вредоносным JavaScript без должной валидации. При просмотре файла в режиме «raw» скрипт выполнялся в контексте приложения.

2. Broken Access Control

Ошибки авторизации и разграничения доступа остаются одной из наиболее распространённых категорий уязвимостей. Для Next.js уже публиковались исследования и исправления, связанные с обходом middleware и нарушением логики авторизации при определённых сценариях обработки запросов. Все cve, что я тут видел, сводятся к обходу различных middleware авторизации. CVE-2025-29927, через подделку заголовка x‑middleware‑subrequest, CVE-2026-44575: Обход через.rsc и segment‑prefetch запросы, CVE-2026-44574: через подделку определенных параметров запроса.

3. Отказ в обслуживании и DOS

Поскольку Next.js переносит часть рендеринга на сервер (SSR, Server Components), он создает дополнительную нагрузку на вычислительные ресурсы. Это особенно заметно под высокой нагрузкой, например, когда SEO‑краулеры одновременно запрашивают множество страниц.
Помимо общего риска увеличения нагрузки, в Next.js существуют конкретные уязвимости, позволяющие злоумышленнику вывести сервер из строя.

  • CVE-2024-56332: «Зависание» Server Actions. Если запрос к Server Action таким образом, что тот остается открытым до истечения времени выполнения функции хостинг‑провайдером, то без жестких ограничений по времени выполнения это приводит к истощению пула соединений и полноценному DoS.

  • CVE-2026-23864 / CVE-2026-23870: Десериализация в React Server Components. Уязвимости в механизме десериализации HTTP‑запросов к Server Components. Злоумышленник отправляет специально сформированный запрос, при десериализации которого возникает рекурсивная обработка или многократное развертывание сжатых данных (zipbomb), что приводит к исчерпанию памяти. 

4. Утечка секретов

Серверные компоненты получают доступ к данным, которые никогда не должны оказаться в браузере пользователя. Я говорю про токены, ключи доступа, внутренние API, конфигурационные параметры.Любая ошибка проектирования может привести к раскрытию этих данных.

5. SSRF

Server‑Side Request Forgery особенно актуальна для серверных приложений. В случае успешной эксплуатации злоумышленник может заставить сервер обращаться к внутренним ресурсам инфраструктуры и использовать приложение как прокси для доступа к внутренним сервисам.

SSRF и связанные уязвимости в Next.js. Конкретные примеры

SSRF (Server‑Side Request Forgery) — это уязвимость, позволяющая атакующему заставить сервер выполнять HTTP‑запросы к внутренним ресурсам, которые обычно недоступны извне.

В контексте Next.js такие атаки особенно опасны, так как могут скомпрометировать всю инфраструктуру приложения.

  • CVE-2024-34351 — SSRF через Server Actions (несанкционированный запрос). В уязвимых версиях Next.js (до 14.1.1) при вызове redirect() внутри Server Action, фреймворк формировал внутренний fetch‑запрос, используя значение заголовка Host из входящего запроса без проверки. Атакующий может отправлить запрос к Server Action, перехватить его и с помощью прокси и подменить Host: localhost:3000 на Host: attacker.com. Next.js, доверяя подмененному заголовку, делает внутренний запрос (HEAD) к серверу атакующего. 

  • CVE-2026-44578 — SSRF через WebSocket Upgrade (прямой доступ). Уязвимость в обработчике WebSocket‑соединений в router‑server.ts (версии с 13.4.13 по 15.5.15). Из‑за отсутствия проверки флагов finished и statusCode, злоумышленник мог инициировать запрос к localhost:80, обходя внутреннюю маршрутизацию.

React2shell

Теперь поговорим о новых рисках, связанных с внедренным протоколом flight и перейдем к самой интересной части — разбору критической уязвимости, получившей название react2shell.
Уязвимость была обнаружена в механизме обработки данных React Server Components и затрагивала обработку запросов к Server Actions, вернее в том, что они небезопасно обрабатывают данные, которые приходят по Flight.

В случае успешной эксплуатации уязвимости злоумышленник мог добиться выполнения произвольного кода на стороне сервера (Remote Code Execution, RCE). Фактически речь шла о возможности выполнить команду от имени процесса веб‑приложения всего одним специально сформированным запросом. Усугубляется все тем, что проэксплуатировать все можно на только инициализированном проекте, даже собственный server action писать не нужно. 

Когда я готовился к докладу, то конечно же читал статьи, в которых говорилось, что эта уязвимость относится к RSC, но почему‑то нигде не видел упоминание server actions. В действительности же, для реализации RCE мы не можем использовать RSC. Посудите сами, из того что я писал RSC — это штука, которая выполняется на сервере, а полезная нагрузка идет на клиент. Поэтому это уязвимость больше относиться к самому flight и server actions, к RSC в меньшей степени. При эксплуатации уязвимости используется как раз обращение к несуществующим server action (может и существующим, но не суть, код исполняется до того, как мы обратимся к конкретному SE).

Для понимания атаки важно помнить, что Flight Protocol восстанавливает объекты из набора чанков и поддерживает ссылки между ними. Именно эта особенность стала основой всей цепочки эксплуатации.

Как выглядит атака: 

При обработке запроса сервер ожидает получить данные определённой структуры, соответствующие внутреннему формату Flight Protocol.

Исследователи обнаружили, что можно сформировать полезную нагрузку таким образом, чтобы она выглядела как легитимный набор чанков и обрабатывалась внутренними механизмами React. Иными словами, злоумышленник заставляет сервер воспринимать специально подготовленные данные как отдельный чанк. Сервер начинает восстанавливать данные и при восстановлении собирает несколько объектов JS. Затем в дело вступает другая уязвимость «заражение птототипа», которую мы реализуем через выполнения метода then одного из восстановленных объектов. 

Ключевая идея заключается не во взломе Server Actions как механизма, а в злоупотреблении логикой обработки Flight Protocol, которая используется в том числе при работе Server Actions.

Подмена структуры чанков

В основе эксплуатации лежит создание набора объектов, которые имитируют структуру легитимных чанков Flight Protocol. Во время обработки сервер получает нормальные объекты протокола, специально подготовленный объект злоумышленника и ссылки между ними. Проблема заключалась в том, что некоторые внутренние проверки не позволяли надёжно отличить реальные объекты протокола от поддельных. В результате вредоносный объект начинал участвовать в обработке наравне с легитимными структурами данных.

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

Полезная нагрузка
Полезная нагрузка

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

  1. proto, через который мы хотим заразить наш прототип 

  2. Constructor, через которых хотим обратиться к глобальному объекту Function

  3. Все что начинаеися с $, имитируя структуру чанка, особенно $@ — ссылка, чтобы чанк разрешался как промис. 

Сам же запрос полностью может выглядеть вот так: 

Как выглядит запрос
Как выглядит запрос

Роль ссылок и Promise‑объектов

Особый интерес для исследователей представлял механизм ссылок между чанками. Flight Protocol поддерживает не только прямые ссылки на объекты, но и ссылки через Promise. Это позволяет React эффективно работать с асинхронными данными и потоковой передачей контента. Однако именно через этот механизм злоумышленникам удалось выйти за пределы ожидаемого сценария обработки данных.

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

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

В частности, исследователи смогли добраться до:

  • Promise.prototype;

  • Function constructor.

А доступ к Function constructor традиционно считается крайне опасным, поскольку позволяет создавать и выполнять произвольный JavaScript‑код во время исполнения программы.

Цепочка эксплуатации

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

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

Шаг 1. Формирование поддельных чанков

Злоумышленник отправляет специально подготовленный запрос к обработчику Server Actions. Внутри запроса содержится набор чанков, которые внешне выглядят корректно для Flight Protocol.

Шаг 2. Разрешение ссылок

Во время обработки React начинает восстанавливать граф объектов и разрешать ссылки между чанками. В этот момент происходит переход к объектам, связанным с Promise.

Шаг 3. Получение доступа к Function Constructor

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

Шаг 4. Подмена внутренних объектов

Следующим этапом становится использование поддельного объекта Response, который воспринимается системой как легитимный внутренний объект обработки Flight Protocol. Из‑за недостаточной проверки происхождения объекта он продолжает участвовать в выполнении логики приложения.

Шаг 5. Выполнение кода

После завершения восстановления структуры данных происходит выполнение сформированного объекта. В результате выполняется команда, переданная злоумышленником в полезной нагрузке. Итогом становится полноценное Remote Code Execution на сервере.

Почему это стало возможным?

С технической точки зрения проблема возникла из‑за сочетания нескольких факторов. Во‑первых, сложной логики восстановления объектов Flight Protocol. Во‑вторых, использования ссылок между чанками и недостаточной проверкой данных при сериализации и десериализации.

Подобные ошибки часто появляются в сложных обработчиках. Чем больше внутренних типов данных поддерживает протокол, тем сложнее гарантировать корректную обработку всех возможных сценариев. В случае react2shell злоумышленники смогли использовать эту сложность себе на пользу.

Что исправили разработчики React

После публикации исследования разработчики React достаточно быстро выпустили исправления. Изменения затронули несколько компонентов экосистемы:

  • react‑server‑dom‑webpack;

  • react‑server‑dom‑parcel;

  • react‑server‑dom‑turbopack.

Основные доработки были направлены на усиление проверок входящих объектов.

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

Практические рекомендации по защите

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

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

Важно контролировать версии:

  • React;

  • Next.js;

  • react‑server‑dom‑*;

  • сопутствующих библиотек.

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

Даже при успешной эксплуатации RCE последствия можно существенно ограничить. Полезными мерами являются: сегментация сети, размещение веб‑приложений в DMZ (хотя dmz считается устаревшим подходом, все просто переходят на zero trust), контроль исходящих соединений, ограничение доступа к внутренним сервисам.

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

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

Поэтому важную роль играют:

  • EDR/XDR‑решения;

  • мониторинг контейнеров или других сред, в которых работает приложение;

  • контроль запуска процессов;

  • анализ аномального поведения приложений.

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

Использование WAF для обнаружения попыток эксплуатации

Для выявления попыток эксплуатации подобных уязвимостей могут использоваться правил WAF. При этом рекомендуется внедрять правила постепенно:

  1. сначала включать только логирование;

  2. анализировать ложные срабатывания;

  3. переводить правила в режим блокировки;

  4. контролировать попытки обхода сигнатур.

Следует учитывать, что Flight Protocol использует потоковую передачу данных и multipart‑запросы. Поэтому слишком агрессивные политики фильтрации могут привести к блокировке легитимного трафика.

На что обращать внимание при анализе трафика

Заголовок Next‑Action

Для вызова Server Actions используется специальный заголовок Next‑Action.
Полезно контролировать неизвестные идентификаторы Server Actions, нестандартные значения заголовков, неожиданные комбинации параметров. На практике можно сформировать список легитимных идентификаторов и отслеживать обращения ко всем остальным.

Аномалии в теле запроса

При анализе полезных нагрузок стоит обращать внимание на признаки Prototype Pollution.Наиболее характерные индикаторы: «_proto_» и «constructor»
Именно эти элементы играют ключевую роль в большинстве вариантов эксплуатации react2shell.

Дополнительными индикаторами могут выступать:

  • then

  • eval

  • child_process

  • execSync

Хотя конкретная полезная нагрузка может меняться, proto и construtor точно быть должны.

Ошибки обработки Server Actions

Во многих сценариях эксплуатации сервер возвращает ошибки обработки Server Actions. Поэтому полезно отслеживать всплески HTTP 500, увеличение количества ошибок обработки Server Actions и аномальное появление digest‑идентификаторов в логах.

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

Выводы

React Server Components и Server Actions открывают новые возможности для разработки современных веб‑приложений. Они позволяют переносить часть логики на сервер, уменьшать объём клиентского JavaScript и повышать производительность пользовательских интерфейсов.

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

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

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