CVE-2025-55182 · React2Shell: 프로토타입 오염을 통한 React Server Components의 RCE

발행: (2026년 5월 3일 PM 04:16 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

TL;DR

React의 Flight 디시리얼라이저는 실제 타입에 관계없이 .then 메서드를 가진 모든 객체를 Promise로 평가합니다. 공격자는 조작된 POST multipart 요청을 통해 Object.prototype.then을 오염시켜, Function 생성자를 이용해 서버가 임의의 JavaScript를 실행하도록 강제할 수 있습니다. 결과는 HTTP 헤더 X-Action-Redirect를 통해 유출됩니다.

  • 인증 없음.
  • 결정적.
  • CVSS v3.1: 10.0 (Critical).

취약점 설명

**React Server Components (RSC)**는 React 19와 함께 Server Actions와 함께 안정화되었습니다. 이 모델에서는 UI 컴포넌트가 서버에서 실행되고 Flight 프로토콜을 통해 통신합니다. 클라이언트가 Server Action을 호출하면 POST multipart 요청에 직렬화된 페이로드를 전송하고, 서버는 이를 역직렬화한 뒤 액션을 실행하고 결과를 스트리밍으로 반환합니다.

Flight 프로토콜은 JSON이 아니라 타입이 지정된 chunks를 사용하는 스트리밍 포맷입니다. 그 핵심 메커니즘은 다음과 같습니다:

if (obj && typeof obj.then === 'function') {
  // Promise로 취급
}

이 가정 때문에 .then 메서드를 가진 어떤 객체라도 Promise로 처리됩니다. 공격자가 Object.prototype.then을 정의하면 런타임의 모든 평범한 객체가 이를 상속받게 되고, 역직렬화 로직은 실제 Promise와 오염된 객체를 구분하지 못합니다. 이 경우 런타임은 공격자가 제어하는 내용에 대해 new Function(_prefix)를 실행하게 됩니다.

영향

⚠️ Next.js 14부터 기본 설정으로 App Router와 React Server Components를 사용하는 모든 Next.js 애플리케이션이 영향을 받습니다. 개발자가 Server Actions를 명시적으로 정의했는지 여부와 관계없이, 취약한 RSC 패키지가 존재하기만 하면 충분합니다.

취약한 버전

  • React 19.0.0 – 19.2.0 (19.0.0, 19.1.0, 19.1.1, 19.2.0 포함)
  • RSC를 사용하는 App Router가 포함된 Next.js 프로젝트에 영향을 줍니다.

악용 체인

  1. 정찰 – React 19.x를 실행하고 App Router를 사용하는 Next.js 애플리케이션을 식별합니다. Next-Action 헤더와 함께 multipart/form-data를 처리하는 모든 엔드포인트는 유효한 목표가 됩니다.
  2. 페이로드 구성__proto__:then을 이용해 Object.prototype을 오염시키는 multipart 본문을 보냅니다. _formData.get 필드는 $1:constructor:constructor로 리다이렉트되고 _prefix는 실행할 JavaScript 코드를 전달합니다.
  3. 전송Next-Action: x 헤더와 함께 루트에 단일 POST 요청을 보냅니다. WAF는 일반적인 multipart 요청으로 인식하고 검사를 우회합니다.
  4. 서버에서 평가 – Flight 디시리얼라이저가 오염된 프로토타입에서 상속된 .then 속성을 가진 객체를 발견하고 new Function(_prefix)를 호출해 공격자의 코드를 실행합니다.
  5. 데이터 추출execSync() 결과가 NEXT_REDIRECT 오류의 다이제스트에 삽입됩니다. Next.js는 이를 307 응답과 X-Action-Redirect: /login?a= 헤더로 변환합니다. 공격자는 파라미터를 디코딩해 출력값을 얻습니다.

최소 페이로드 예시 (cURL)

curl -X POST https://victim.com/ \
  -F '__proto__:then=()=>({then:()=>({})})' \
  -F '_formData.get=$1:constructor:constructor' \
  -F '_prefix=return require("child_process").execSync("id").toString()' \
  -H 'Next-Action: x'

일반적인 결과

  • whoami, id, uname -a가 취약한 Node.js 서버에서 실행됩니다.
  • 파일 업로드, 쉘 인젝션 또는 인증이 필요하지 않습니다.

취약한 코드 (패치 전)

// VULNERABLE — React 19.0.0 / 19.1.0 / 19.1.1 / 19.2.0
if (obj && typeof obj.then === 'function') {
  // comprobación conductual — bypasseable vía cadena de prototipos
}

패치

hasOwnProperty를 사용한 가드를 추가하여 프로토타입 체인의 탐색을 차단합니다:

- resolvedValue = resolvedValue[key];
+ if (!resolvedValue.hasOwnProperty(key)) break;
+ resolvedValue = resolvedValue[key];

패치 검증

node -e "const r = require('react'); const [maj,min,pat] = r.version.split('.').map(Number);
  console.log('React:', r.version, (maj===19 && (min<2||(min===2&&pat<1))) ? '❌ VULNERABLE' : '✓ Parcheado')"

패치 후 권고

초기 패치된 버전(19.0.1, 19.1.2, 19.2.1)에서는 두 개의 파생 CVE가 도입되었습니다:

  • CVE‑2025‑55184 – 서비스 거부(DoS), CVSS 7.5
  • CVE‑2025‑55183 – 소스 코드 노출, CVSS 5.3

19.0.2, 19.1.3 또는 19.2.2로 업데이트하는 것이 권장됩니다.

성찰

동작 기반 신뢰(typeof obj.then === 'function')는 정체성 기반 신뢰보다 약합니다. 모든 thenable을 허용하는 유연성 때문에 prototype pollution이 원격 코드 실행을 위한 마스터 키가 되었습니다.

참고 문헌

  • 전체 분석 → blog.deviannt.com
  • CVE‑2025‑55182 – React2Shell
  • — devianntsec, 보안 조사 및 기타
0 조회
Back to Blog

관련 글

더 보기 »