관심있는 주제

React2Shell: React Server Components에서 발생한 치명적 RCE 취약점 정리

데이터분석뉴비 2025. 12. 12. 20:01
728x90

 

0. 왜 이 이슈를 정리할 가치가 있나

2025년 말 공개된 React2Shell 취약점(CVE-2025-55182) 은 단순한 “라이브러리 버그”가 아니다.
이 사건은 다음 질문을 강하게 던진다.

“우리가 프레임워크를 신뢰한다는 건, 어디까지 책임을 위임하는 걸까?”

특히 React Server Components(RSC) 를 사용하는 서비스라면,
이 취약점은 설계 수준에서의 리스크를 다시 보게 만드는 계기다.

 

1. React2Shell이란 무엇인가

React2Shell
React의 Server Components(RSC) 요청을 처리하는 과정에서
👉 역직렬화(deserialization) 로직을 악용해 서버에서 임의 코드 실행(RCE) 이 가능해지는 취약점이다.

  • 영향도: CVSS 10.0 (Critical)
  • 공격 결과:
    • 인증 없이 서버 코드 실행
    • 서버 환경변수, 시크릿, 파일 접근 가능
    • 컨테이너/VM 장악 가능

중요한 점은 이거다.

❌ “React 쓰면 다 위험하다”
“RSC 서버 엔드포인트가 열려 있으면 위험하다”

 

 

― “역직렬화 로직 악용”을 아주 쉽게 설명하면

먼저, 우리가 평소에 안전하다고 믿는 상황부터 보자

보통 서버 API는 이런 식이다.

POST /login
{
  "email": "user@test.com",
  "password": "1234"
}

서버는 이렇게 생각한다.

“아, 이건 데이터구나.
문자열이고, 숫자고, 그냥 값이네.”

그래서 서버는

  • JSON을 객체로 변환(= 역직렬화) 하고
  • 값만 꺼내서 로직에 사용한다

이 경우 공격자가 할 수 있는 건 많아야:

  • 이상한 문자열 넣기
  • 범위 초과 숫자 넣기
    정도다.

👉 데이터는 데이터일 뿐, 실행되지는 않는다.

 

그런데 React Server Components(RSC)는 다르다

RSC에서 서버는 단순 데이터를 받는 게 아니다.

서버는 이런 걸 받는다:

“이 컴포넌트를 렌더링해라”
“이 함수 참조를 복원해라”
“이 구조를 다시 서버에서 이어 붙여라”

즉,

❌ “값만 복원”
“구조와 의미까지 복원”

을 한다.

이게 핵심이다.

 

역직렬화(deserialization)란 정확히 뭐냐

직렬화

  • 객체 / 구조 → 전송 가능한 형태(JSON, form-data 등)

역직렬화

  • 전송된 값 → 다시 객체·구조로 복원

문제는 여기서 생긴다.

React2Shell의 핵심 문제

React RSC 서버는
클라이언트가 보낸 요청을 이렇게 믿고 있었다.

“이건 React가 만든 정상적인 구조일 거야”

그래서 서버는:

  • 요청을 파싱하고
  • 내부 객체로 복원하고
  • 그 구조를 기반으로 서버 로직을 진행

그런데 공격자는 이렇게 생각했다.

“그 구조를 내가 직접 만들어서 보내면 어떨까?”


아주 단순한 비유로 설명하면

🏠 정상 상황

  • 손님이 조립된 가구를 주문
  • 서버는 “아, 이건 정상적인 가구 구조네” 하고 설치

💣 공격 상황

  • 공격자가 가짜 조립 설명서를 보냄
  • 서버는 설명서를 그대로 믿고 조립
  • 그런데 그 설명서엔:
    • “여기서 전기선 연결”
    • “여기서 문 대신 폭탄 설치” 같은 단계가 숨어 있음

👉 서버는 설명서를 실행해버린 셈이다.


🔹 기술적으로 무슨 일이 벌어졌나 (쉽게)

React2Shell에서는:

  • multipart/form-data 요청에
  • 의도하지 않은 객체 구조를 주입
  • 서버의 역직렬화 로직이 이를 그대로 복원
  • JS의 동적 특성(타입 검사 부족, 구조 신뢰)을 이용해
  • 서버 코드 실행 경로까지 침투

중요한 점:

공격자는
❌ 서버 코드를 업로드한 게 아니다
❌ eval을 직접 호출한 것도 아니다

“서버가 스스로 실행하게 만들었다”


🔹 왜 이게 이렇게 위험한가

  • 인증 필요 없음
  • 사용자 계정 필요 없음
  • 단순 POST 요청 하나로 가능
  • 서버 권한으로 실행됨

그래서 이 취약점의 결과는:

“입력값을 조작했을 뿐인데, 서버 쉘을 얻는다”

→ React2Shell이라는 이름이 붙은 이유다.

 

 

2. 어떤 환경이 영향을 받는가 (GPT가 정리해준 내용)

영향을 받는 패키지

React RSC 내부 구현 패키지들:

  • react-server-dom-webpack
  • react-server-dom-parcel
  • react-server-dom-turbopack

취약 버전

  • 19.0
  • 19.1.0
  • 19.1.1
  • 19.2.0

안전한 버전

  • 19.0.1
  • 19.1.2
  • 19.2.1

⚠️ 직접 설치하지 않았어도
Next.js App Router, RSC 사용 시 의존성으로 포함돼 있을 수 있다.

 

 

3. 이 취약점은 어떻게 발견됐나

  • 보안 연구자 Lachlan Davidson이 발견
  • 2025-11-29: React 팀에 비공개 제보
  • PoC 제작 및 내부 검증
  • 2025-12-03: React 공식 보안 공지 공개

이후:

  • GitHub에 PoC 확산
  • 자동 스캐닝·대량 공격 정황 다수 보고
  • WAF 우회 변종까지 등장

👉 “조용히 패치하고 끝낼 수 있는 이슈는 아니었다”

 

4. 실제 공격 시나리오 (현실적인 관점)

공격자는 다음을 노린다.

  1. 인터넷에 노출된 RSC 서버 탐색
  2. 특정 RSC 엔드포인트로 POST 요청
  3. 조작된 multipart/form-data 페이로드 전송
  4. 서버에서 코드 실행
  5. 환경변수/시크릿 탈취 → 추가 침투

특징:

  • 인증 불필요
  • 사용자 계정 필요 없음
  • 봇으로 대규모 스캔 가능

 

5. 이미 만든 서비스는 어떻게 해야 하나 (실무 가이드)

✅ 1단계: 해당 여부 확인

  • RSC / Next.js App Router 사용 중인가?
  • react-server-dom-* 패키지가 의존성에 포함돼 있는가?
 
npm ls react-server-dom-webpack
pnpm why react-server-dom-webpack

 

✅ 2단계: 최우선 대응 — 패치

  • React를 안전 버전으로 즉시 업그레이드
  • Next.js 등 프레임워크도 함께 업데이트 권장

❗ WAF, 차단 룰은 “보조 수단”일 뿐
패치가 유일한 근본 해결책

 

✅ 3단계: 패치 전·후 방어 강화

  • RSC 엔드포인트 접근 최소화
  • 비정상 POST / multipart 요청 로깅·레이트리밋
  • 컨테이너 권한 최소화
  • 서버 egress 제한

✅ 4단계: “이미 침해됐을 가능성” 점검

  • RSC 경로로의 대량 POST 로그
  • 알 수 없는 프로세스/파일 생성 여부
  • 환경변수, 토큰 전면 로테이션
  • 배포 무결성 확인

6. 이 사건에서 개발자가 배워야 할 것

1️⃣ 프레임워크 ≠ 신뢰 경계

  • “프레임워크 내부니까 안전하다”는 가정은 위험
  • 역직렬화 + 동적 실행은 항상 최상위 위험군

2️⃣ 기능을 켜는 순간 공격면이 늘어난다

  • RSC는 “렌더링 최적화 기능”이 아니라
  • 서버 실행 모델의 변화

3️⃣ 보안은 사후 대응이 아니라 설계 문제

  • Threat Modeling
  • Dependency 보안 공지 구독
  • CI 단계 SCA(취약점 스캔) 필수화

 

 

 

 

 

 

 

 

https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components?utm_source=chatgpt.com

 

Critical Security Vulnerability in React Server Components – React

The library for web and native user interfaces

react.dev

 

 

https://www.youtube.com/watch?v=4G62BiyMi2s