React와 Next.js의 원격 코드 실행(RCE) 취약점
(github.com/vercel)- React와 Next.js에서 원격 코드 실행(RCE)이 가능한 보안 취약점이 보고됨
- 이 문제는 Next.js 패키지 내부에서 발생하며, 공격자가 악의적인 입력을 통해 임의의 코드 실행을 유도할 수 있음
- Vercel은 GitHub 보안 권고(GHSA-9qr9-h5gf-34mp) 를 통해 해당 취약점을 공개하고, 업데이트 버전을 배포함
- 사용자는 최신 버전으로 업그레이드하여 취약점을 완화해야 함
- 이번 사례는 프레임워크 수준의 보안 관리 중요성을 다시 부각시킴
RCE 취약점 개요
-
Next.js와 React 환경에서 원격 코드 실행이 가능한 취약점이 발견됨
- 공격자가 서버 측에서 임의의 JavaScript 코드를 실행할 수 있는 위험 존재
- 이 취약점은 Next.js 패키지 내부 코드 처리 과정에서 발생
- 구체적인 취약 함수나 모듈에 대한 세부 설명은 공개되지 않음
영향 및 대응
-
Vercel은 GitHub 보안 권고(GHSA-9qr9-h5gf-34mp) 를 통해 문제를 공식 발표
- 해당 권고는 Next.js 저장소의 보안 공지 섹션에 게시됨
- 취약점이 존재하는 버전은 명시되지 않았으나, 업데이트 버전 배포가 이루어짐
- 사용자에게 최신 안정 버전으로 업그레이드할 것을 권장
보안 권고 및 조치
-
Next.js 패키지를 사용하는 모든 프로젝트는 즉시 버전 확인 필요
-
package.json의 Next.js 버전을 최신으로 유지해야 함
-
- Vercel은 수정된 버전 배포 외 추가적인 완화 조치에 대한 언급 없음
- 취약점의 세부 기술적 내용은 공개되지 않은 상태로, 보안상 이유로 제한된 정보만 제공됨
중요성
- 이번 취약점은 서버 렌더링 환경에서의 코드 실행 위험을 보여줌
- React 및 Next.js 기반 서비스 운영자는 보안 업데이트를 정기적으로 적용해야 함
- 프레임워크 수준의 보안 취약점이 전체 애플리케이션 보안에 직접적 영향을 미칠 수 있음
Hacker News 의견
-
이번 취약점은 RSC/server actions 도입 때부터 경고받던 최악의 시나리오가 현실화된 사례임
서버가 클라이언트의 신뢰할 수 없는 입력을 그대로 역직렬화해 모듈과 export 이름을 찾아 실행했음
hasOwnProperty패치로 막을 수는 있지만, 근본적으로 React가 RPC 레이어를 만든다는 사실을 명확히 인식하지 않았던 게 문제임
gRPC나 SOAP 같은 전통적 RPC 프레임워크는 명시적 스키마와 서비스 정의로 경계를 분명히 하지만, React는 번들러가 볼 수 있는 모든 API를 노출하는 방식이라 위험함
이런 설계로 인한 보안 문제는 앞으로도 반복될 가능성이 높음- 이건 단순히 부주의함의 문제로 보임
명시적 스키마가 있더라도, 마지막 단계에서 신뢰할 수 없는 입력이 서버 네임스페이스의 아무 객체나 참조할 수 있게 두면 소용없음 - 실제로는 클라이언트가 요청하는 모든 엔드포인트가 노출되는 게 아님
"use server"로 표시된 함수만 노출되고, React 팀도 RPC 시스템을 설계하고 있다는 걸 인식하고 있음
이런 버그는 다른 RPC 시스템에서도 충분히 발생할 수 있음 (React 기여자임) - 경고를 받았는데도 이런 일이 생겼다는 건 결국 부주의한 구현으로밖에 볼 수 없음
- 일반 사용자 입장에서는 이 접근법을 쓰지 않으면 안전한 건지 궁금함
하지만 오래된 비공개 레포를 유지하는 것도 좋은 선택은 아님
- 이건 단순히 부주의함의 문제로 보임
-
Next는 정적 빌드가 유일한 장점임
그 지원이 중단되면 더 이상 사용할 이유가 없음 -
Facebook/Meta의 보안 권고문에 따르면, React Server Components 19.0.0~19.2.0 버전에 인증 전 원격 코드 실행(RCE) 취약점이 존재함
React 공식 블로그 공지에서도, 클라이언트가 서버 함수를 호출할 수 있는 구조 때문에 공격자가 악의적인 HTTP 요청을 만들어 서버에서 임의 코드를 실행할 수 있다고 설명함- 수정 내용이
hasOwnProperty검사 추가라면, 공격은 아마도 프로토타입 체인의 속성(__proto__등)을 참조하는 방식이었을 것 같음 - “클라이언트가 서버 함수를 호출할 수 있다”는 문장이 의도된 기능이라면 꽤 무서운 설계로 느껴짐
- 수정 내용이
-
수정 커밋은 이 커밋으로 보임
여러 변경과 함께 스쿼시되어 세부 내용이 가려진 듯함
코드에서 노출되는 함수 목록을 화이트리스트 방식으로 제한하는 패턴이 4곳에서 보임- 혹은 이 커밋이 원인일 수도 있음 (“중대한 보안 취약점 수정” 명시)
-
Vercel은 이미 플랫폼 수준 보호로 악성 요청 패턴을 차단하고 있음
공지 참고
Cloudflare도 WAF 규칙으로 선제 대응함 -
PoC 저장소를 참고해 취약점을 재현해봤음
- 패치된
react-server-dom-webpack으로도 RCE가 실행돼서, 메커니즘이 완전히 맞지는 않은 듯함
실제 Next.js 프로젝트에서 데모를 보여주면 좋겠음 - 그래도 정리해준 글이 정말 인상적이었음
- 패치된
-
“Vercel 없이 RCE는 없다”는 말이 나올 정도로 이번 사건은 호스팅 환경과 보안의 상관관계를 드러냄
-
CVE 점수 10.0은 이렇게 널리 쓰이는 프로젝트에선 충격적인 수치임
- 영향을 받은 패키지 react-server-dom-webpack은 “실험적이며 위험을 감수하라”고 명시돼 있음
그런데도 주간 다운로드가 31만 건이 넘음 - 이런 사건에서는 CVSS 10.0을 명확히 표기해야 PR성 발언으로 덮이지 않음
- React는 널리 쓰이지만, React Server Components는 아직 그렇게 보편적이지 않음
- 영향을 받은 패키지 react-server-dom-webpack은 “실험적이며 위험을 감수하라”고 명시돼 있음
-
React 팀이 왜 이렇게 혼란스러운 기능에 시간을 쓰는지 이해하기 어려움
SSR보다 나은 점이 뭔지, 성능 향상이 얼마나 되는지도 의문임
Hook 도입 이후 개발자 경험이 나빠졌는데, 그걸 개선하기보다는 또 다른 복잡성을 추가함
차라리 JS 본연의 제어 흐름을 컴포넌트 로직에서 자연스럽게 쓸 수 있게 해줬으면 함- Server Components는 SSR과 직접 관련이 없음
나는 이를 컴포넌트화된 BFF(Backend for Frontend) 계층으로 봄
각 UI 조각이 대응되는 백엔드 로직과 직접 연결되어,fetch호출 없이 데이터를 가져올 수 있음
이렇게 하면 프론트와 백엔드가 함께 진화하기 쉬워지고, 필요한 데이터만 세밀하게 로드할 수 있음
결국 UI 전용 서버 로직을 컴포넌트 구조 안에 자연스럽게 녹여낼 수 있음 - React가 “기본 프레임워크”가 된 게 아쉬움
Svelte나 React의 컴파일러 기반 모델이 훨씬 다루기 편함 - 근본적으로는 JS 언어의 한계와 경쟁 부재가 문제라고 생각함
Vue, Svelte, Angular 등은 모두 별도 컴파일러와 파일 확장이 필요함
반면 React/JSX는 전처리기 단계에서 이미 특혜를 받음
Rust는 매크로 시스템으로 이런 문제를 해결했음 — 예를 들어 Leptos나 Yew는 표준.rs파일 안에서 JSX나 HTML 템플릿을 지원함
JS가 이런 확장성을 갖추지 못하면, 웹은 앞으로도 복잡하고 비효율적인 환경에 머물 가능성이 큼 - 나는 hooks를 좋아함 :)
- RSC는 SSR을 빠르게 만들지 못한 결과로 나온 대체 시도임
클라이언트 측 부하를 줄이려 했지만, 그마저도 실패한 느낌임
- Server Components는 SSR과 직접 관련이 없음
-
React 블로그의 상세 설명도 참고할 만함