내 Next.js 앱에서 실제 RCE 공격을 감지하고 차단한 방법 (CVE-2025-55182 / React2Shell)
Source: Dev.to

지난 주, 웹 앱을 개발하면서 겪은 가장 충격적인 보안 사고 중 하나를 경험했습니다.
프로덕션 Next.js 애플리케이션이 원격 코드 실행 (RCE) 을 시도하는 공격자들의 표적이 되었고, 근본 원인은 새로 공개된 React Server Components 취약점이었습니다.
이 글에서는 무슨 일이 있었는지, 어떻게 문제를 진단했는지, 어떻게 패치를 적용했는지, 그리고 인프라를 강화하기 위해 어떤 조치를 취했는지를 다룹니다.
1) 첫 번째 징후: 컨테이너 내 의심스러운 로그
Docker 컨테이너를 확인하던 중 이상한 로그가 눈에 띄었습니다:
/bin/sh: curl: not found
/base64 -d | bash
ping: bad address
cat: can't open '.env.production'
공격자는 다음과 같은 행동을 시도하고 있었습니다:
- 악성 스크립트를 다운로드하려고 시도
- 환경 변수를 탈취하려고 시도
/tmp에 파일을 남김- 정찰 명령을 실행
- base64‑인코딩된 페이로드를 주입
이 단계에서는 파일 시스템에 지속적인 흔적이 남지 않았고, 컨테이너 재시작 시 악성 바이너리도 사라졌습니다—좋은 신호였지만, 애플리케이션 내부에서 쉘 명령을 실행하려는 시도가 있었음은 분명했습니다.
2) 근본 원인 조사
우선 내 서버‑사이드 코드를 살펴보았습니다:
- 모든 라우트 핸들러 검토
- 모든 Server Action 감사
child_process.exec,spawn, CLI 래퍼 등 사용 여부 검색
내 코드에서는 쉘 명령을 실행하는 부분이 없었으므로, 다음으로 의심한 것은 프레임워크 수준의 취약점이었습니다.
범인: CVE‑2025‑55182 (React2Shell)
내 앱은 취약한 React Server Components 빌드를 포함하고 있는 Next.js 버전을 사용하고 있었으며, 이는 CVE‑2025‑55182 – React2Shell 에 의해 영향을 받는 버전이었습니다.
이 취약점은 React의 RSC/Flight 프로토콜에서 안전하지 않은 역직렬화로 인해 발생하는 사전 인증 RCE입니다. 단 하나의 조작된 HTTP 요청만으로 공격자는 Node.js 서버 내부에서 임의 코드를 실행할 수 있었으며, 맞춤형 API 엔드포인트가 없어도 가능했습니다.
공개된 PoC를 내 실행 중인 앱에 적용해 보니… 성공했습니다. 모든 것이 갑자기 명확해졌습니다.
3) 취약점 해결
React 팀이 패치를 배포했고, Next.js는 취약 패키지를 업그레이드하기 위한 공식 도구를 제공했습니다.
npx fix-react2shell-next
위 명령을 실행하면 다음이 업데이트됩니다:
- React RSC 내부 구현
- 취약한 코드 경로에 의존하는 Next.js 내부
깨끗한 Docker 이미지로 앱을 다시 빌드하고 재배포했습니다. 그 후 PoC를 다시 실행했을 때: 익스플로잇 실패. 완전히. 문제가 해결되었습니다.

취약한 Next.js 앱에서 npx fix-react2shell-next를 실행해 활성 취약점을 확인하고 공식 패치를 적용하는 과정.
4) 인프라 강화 (이것이 나를 구함)
취약점 자체는 존재했지만, 공격자는 지속성을 확보하거나 호스트로 권한을 상승시키지 못했습니다. 이는 하드닝된 Docker 환경 덕분이었습니다:
- 읽기 전용 루트 파일시스템
noexec옵션이 적용된/tmp마운트- 모든 Linux 권한(capability) 삭제
no-new-privileges활성화- 컨테이너 내부에
bash나curl미설치 - 격리된 쓰기 가능한 디렉터리만 존재
- Nginx 레이트 리밋 및 리버스 프록시 필터링
이러한 레이어들은 파일 실행, 스크립트 다운로드, 지속성 설치, 크론 수정, 권한 상승, 격리된 볼륨 외부 쓰기 등을 차단했습니다. 결국 취약점은 RCE를 허용했지만, 환경이 전체 침해로 이어지는 것을 막았습니다.
5) 사고 후 조치
패치를 적용한 뒤 추가로 수행한 작업:
- 모든 환경 비밀키 교체
- 깨끗한 이미지로 전체 재배포
- 악성 파일이 남아 있지 않은지 검증
- 로그를 검토해 공격 시도가 차단됐는지 확인
우리가 자주 말하듯, 보안은 하나의 문제를 고치는 것이 아니라 지속적인 과정입니다.
6) 개발자를 위한 핵심 교훈
- 빠르게 패치 – React2Shell은 이미 실전에서 악용되고 있었습니다. Next.js + RSC를 사용한다면 즉시 업데이트하세요.
- 최소 권한이 생명을 구한다 – 읽기 전용 루트 파일시스템만으로도 실제 공격 체인의 약 80 %를 차단할 수 있습니다.
- 내 코드가 완벽하다고 믿지 말라 – 프레임워크 취약점은 언제든 발생합니다. 공격자는 빠르게 움직입니다.
- 다중 방어층을 구축 – 단일 방어책만으로는 이 공격을 막을 수 없었지만, 여러 방어가 합쳐져 차단되었습니다.
- 모든 것을 모니터링 – 로그가 공격을 너무 늦기 전에 포착했습니다.
7) 결론
이번 경험은 강렬했지만 매우 교육적이었습니다. 이런 사고는 누구에게든 일어날 수 있으며, 피해자마다 고유한 이야기가 있습니다. 최신 버전을 유지하고, 런타임 환경을 하드닝하며, 취약점이 발생할 것을 전제로 인프라를 준비하는 것이 얼마나 중요한지 다시 한 번 깨달았습니다.
이 글을 읽는 사람 중 한 명이라도 애플리케이션을 패치하거나 보안 설정을 개선한다면, 글을 쓴 보람이 충분히 있습니다.
References
- CVE‑2025‑55182 – React2Shell 분석: https://www.trendmicro.com/en_us/research/25/l/CVE-2025-55182-analysis-poc-itw.html
- React 보안 발표: https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
- 공식 패치 도구:
npx fix-react2shell-next