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

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

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

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

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

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/ejpir/cve-2025-55182-research
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийОбход WAFСтатьи и ИсследованияОбучение и ОбразованиеРазработка Полезной Нагрузки
GitHubejpir/cve-2025-55182-research

CVE-2025-55182-research

Технический proof-of-concept и углубленный анализ CVE-2025-55182, критической уязвимости RCE в React's Flight Protocol через обход пути, внедрение поддельных фрагментов и злоупотребление обработчиком $B.

Репозиторий
795202299 месяцев назадПроверено Kitploit

Популярное

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

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

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

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

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

CVE-2025-55182 - RCE в React Server Components

ПРИМЕЧАНИЕ: Написано AI/Claude

https://github.com/ejpir/CVE-2025-55182-bypass

TL;DR

CVE-2025-55182 — это критическая уязвимость RCE в протоколе Flight от React. Атака сочетает path traversal + внедрение поддельного чанка + злоупотребление обработчиком $B для выполнения Function(attacker_code).

Большое спасибо maple3142 за рабочую цепочку эксплуатации!


Эксплойт

Обзор атаки

Эксплойт использует три поля формы для создания вредоносной нагрузки:

  1. Создает поддельный объект чанка с самореференсным then (поле 1 $@0 → поле 0)
  2. Встраивает поддельный _response с _formData.get, установленным в $1:constructor:constructor
  3. Запускает обработчик $B, который вызывает response._formData.get(response._prefix + id)
  4. Path traversal разрешает _formData.get → Function, выполняя Function(code)

Поток эксплуатации```

┌─────────────────────────────────────────────────────────────────────┐ │ 1. Attacker sends multipart form with fake chunk object │ │ → decodeReply() parses form fields 0, 1, 2 │ │ → Object has: then, status, value, _response │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 2. Self-reference makes object thenable with real function │ │ → then: "$1:proto:then" → Chunk.prototype.then │ │ → Chunk.prototype.then(this) calls initializeModelChunk(this) │ │ → Uses this._response (attacker's fake _response) │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 3. parseModelString() handles "$B1337" reference │ │ → case "B": return response._formData.get(response._prefix+id) │ │ → Calls _formData.get with attacker's _prefix + "1337" │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 4. getOutlinedModel() resolves _formData.get (lazy evaluation): │ │ → "$1:constructor:constructor" traverses prototype chain │ │ → Returns Function constructor │ │ → Function(code + "1337") → RCE │ └─────────────────────────────────────────────────────────────────────┘

### Ключевые компоненты

| Компонент | Назначение |
|-----------|---------|
| `then: "$1:__proto__:then"` | Самоссылающийся thenable; чанк 1 (`$@0`) указывает обратно на чанк 0 |
| `status: "resolved_model"` | Делает объект похожим на валидный React чанк |
| `reason: -1` | Устанавливает rootReference в undefined (избегает конфликтов ссылок) |
| `value: '{"then":"$B1337"}'` | Вложенная полезная нагрузка, которая запускает обработчик `$B` |
| `_response._prefix` | Содержит строку кода RCE |
| `_response._chunks: "$Q2"` | Пустая Map для предотвращения сбоев во время обработки чанков |
| `_response._formData.get` | Указывает на `Function` через `$1:constructor:constructor` |

### Детальный разбор компонента

#### Структура поля формы

Эксплойт использует три поля формы с циклическими ссылками:```
Field 0: {"then":"$1:__proto__:then", "status":"resolved_model", ...}
Field 1: "$@0"    ← references back to field 0
Field 2: []       ← empty array for _chunks Map

Self-Referential Thenable (then)

then: "$1:__proto__:then" создает самоссылку, которая разрешается в настоящую функцию:``` $1:proto:then ↓ $1 → chunk 1 → "$@0" → getChunk(0) → Chunk object ↓ Chunk.proto.then → Chunk.prototype.then (actual function!)

**Почему это критично:**

1. `then` разрешается в `Chunk.prototype.then` - реальная вызываемая функция
2. Это делает поддельный объект валидным thenable
3. При ожидании (await) JS вызывает `obj.then(resolve, reject)`
4. `Chunk.prototype.then` выполняется с поддельным объектом в качестве `this`:```javascript
Chunk.prototype.then = function (resolve, reject) {
  switch (this.status) {  // this.status = "resolved_model" ✓
    case "resolved_model":
      initializeModelChunk(this);  // fake object passed!
  1. initializeModelChunk(this) использует this._response - поддельный _response атакующего:```javascript value = reviveModel( chunk._response, // ← attacker's fake _response! ... );
**Без самореференции** поддельный `_response` никогда бы не использовался. Самореференция заставляет `Chunk.prototype.then` обрабатывать объект злоумышленника как настоящий Chunk.

#### Двухэтапный Thenable-триггер (`value`)

Поле `value` содержит вложенную строку JSON с другим thenable:```json
{"then":"$B1337"}

Шаг 1: Самореферентный then внешнего объекта запускает обработку фрагментов

Шаг 2: Когда React разрешает модель, он анализирует value и встречает другой thenable с then: "$B1337". Префикс $B запускает обработчик:```javascript case "B": return response._formData.get(response._prefix + obj); // obj = "1337"

`_formData.get` является `"$1:constructor:constructor"` → `getOutlinedModel()` разрешается в `Function`.

Это становится: `Function(code + "1337")` → валидный JS, потому что `1337` — это просто завершающее выражение.

#### Защитное дополнение (`_chunks`)

Фальшивому `_response` требуется валидное свойство `_chunks`, чтобы предотвратить сбои:```
Form field "2": []           ← empty array
_chunks: "$Q2"               ← $Q = Map type, creates new Map([])

Реактовский внутренний код может обращаться к response._chunks.get() или response._chunks.has() в процессе обработки. Пустой Map удовлетворяет этим вызовам без ошибок, позволяя выполнению дойти до уязвимого обработчика $B.


Уязвимые пути выполнения

ПутьФункцияНазначение в эксплойте
Обход путиgetOutlinedModel()Преобразует $1:constructor:constructor → Function
Инъекция поддельного _responseinitializeModelChunk()Использует chunk._response атакующего
Обработчик $BparseModelString()Вызывает _formData.get(_prefix + id) → RCE

decodeReply() является точкой входа, сама по себе не уязвима.

Обход пути (getOutlinedModel()):```javascript for (key = 1; key < reference.length; key++) parentObject = parentObject[reference[key]]; // No validation!

**Использование поддельного ответа** (`initializeModelChunk()`):```javascript
value = reviveModel(
  chunk._response,  // Uses chunk._response directly!
  { "": rawModel },
  ...
);

$B Обработчик RCE (parseModelString()):```javascript case "B": return response._formData.get(response._prefix + obj); // RCE!

---

## Исправление (19.2.1)

Патч включает несколько исправлений:

1. **`RESPONSE_SYMBOL` в `initializeModelChunk()`** - Критическое исправление   ```javascript
   // BEFORE: chunk._response (attacker can set via JSON)
   value = reviveModel(chunk._response, ...);
Скачать инструмент