Next.js 보안 취약점 이슈에 대하여...

sujin·2025년 12월 27일
post-thumbnail

어느 평화롭던 토요일 아침, AWS에서 메일을 받게되면서 이야기는 시작됩니다.😇

프론트 서버 한대가 죽었다는 알림이었는데요. 트래픽이 몰리거나 메모리 문제 혹은 DDoS 공격 등으로 인해 간헐적으로 발생하던 문제였기 때문에 메뉴얼대로 처리하고 원인에 대해서는 월요일에 파악하자고 하면 마무리되는 듯 했습니다. 그런데 한 10분 정도 지났을까요? 또 다시 서버 한대가 죽었다는 AWS 메일이 왔습니다.

뭔가 잘못됐다는 것을 느꼈고, 몇일 전 Next.js 보안 이슈가 발표됐다는 것 알게되었습니다. 이번 이슈는 단순 라이브러리 경고 수준이 아닌, 구조적으로 서버 코드 실행까지 이어질 수 있는 취약점이었기 때문에 실제 운영 관점에서 많은 점을 다시 점검하게 된 계기였습니다.

이 글에서는 취약점이 어떤 문제였는지, 서비스에 어떤 영향을 줄 수 있었는지, 어떻게 대응했는지 경험을 바탕으로 정리했습니다.


React2Shell 이 뭔데?

React2Shell(CVE-2025-55182) 은 React Server Components의 RSC 프로토콜에서 발견된 취약점으로, CVSS 점수가 10.0인 최고 등급의 보안 취약점입니다.
React 19의 react-server 패키지가 RSC Flight 프로토콜 처리 과정에서 안전하지 않은 역직렬화로 인해 악의적인 HTTP 요청을 통해 서버에 임의의 코드를 실행 할 수 있는 문제입니다.

이 취약점이 특히 심각한 이유는 다음과 같습니다.

1. 기본 설정만으로 취약

create-next-app 으로 만든 기본 프로젝트도 공격 대상이 됩니다. Next.js 15의 App Router는 RSC를 기본으로 사용하는데, 바로 이 구조 자체에 취약점이 있었습니다.

2. 인증 없는 원격 코드 실행

공격자는 인증 없이 단 하나의 조작된 HTTP 요청만으로 서버에서 코드를 실행할 수 있습니다.

3. 광범위한 영향

React 사용자의 82%, 클라우드 환경의 39%가 취약한 버전을 사용 중이었습니다. 수많은 서비스가 잠재적인 공격 대상이었던 것입니다.

4. 빠른 무기화

취약점 공개 후 불과 몇 시간 만에 실제 공격이 시작되었다고 합니다. 중국 국가 지원 해킹 그룹을 포함한 여러 공각자들이 즉각 움지였고, 저희 서비스 또한 그 표적이 되었던 것입니다.


문제가 발생한 이유는?

상황

RSC를 사용하는 곳에 직렬화하는 부분에서 의도적으로 조작된 URL이 들어오게 되었습니다. 그 URL은 사실상 서비스에서 제공하지 않는 비정상적인 요청이었는데도 불구하고 Next.js에서 정상적인 요청으로 받아들였습니다.

여기서 문제는 Next.js가 next-action 헤더가 포함된 요청을 받으면 개발자가 실제로 서버 액션을 작성했는지 여부와 상관없이 무조건 해당 요청의 데이터를 처리하려고 시도한다는 점이었습니다. 공격자는 이 점을 악용해 next-action 헤어만 붙여서 악성 코드를 서버로 전송할 수 있었습니다.

문제

그 조작된 요청은 중국 암호화폐 채굴 스크립트를 실행하는 URL이었고, 그 공격으로 인해 CPU 사용률이 급격히 증가하면서 서버가 계속해서 다운되는 현상이 발생했습니다.

공격이 성공하면 서버에서는

  • cpu 사용률 급증
  • 외부 중국 서버로 지속적인 네트워크 연결 시도
  • 헬스체크 실패로 인스턴스 종료
  • 오토 스케일링으로 새 인스턴스 생성 -> 다시 공격 -> 반복

처음에는 한두대였지만, 몇 분 간격으로 추가적으로 서버가 다운되면서 상황은 심각해졌습니다.

원인

React2Shell(CVE-2025-55182)의 핵심 원인은 안전하지 않은 역직렬화(Unsafe Deserialization) 문제입니다.

React Server Components는 클라이언트와 서버가 데이터를 주고받을 때 Flight 프로토콜이라는 방식을 사용합니다. 이 과정에서 데이터를 "직렬화(문자열로 변환)" → "전송" → "역직렬화(다시 객체로 복원)" 하는데, 바로 이 역직렬화 과정에서 보안 검증이 부족했습니다.

  1. 공격자가 겉으로 보기엔 정상적인 데이터를 전송
  2. Next.js 서버가 이 데이터를 받아서 처리하기 시작
  3. 숨겨진 특수 속성들이 Javascript의 핵심 기능에 접근
  4. 공격자가 서버에서 원하는 코드를 실행

Next.js는 받은 데이터가 이상한 속성이 포함되어 있는지, 위험 코드가 실행될 수 있는지 등을 제대로 확인하지 않았습니다. 이 취약점이 특히 위험한 이유는 인증이 불필요하고 기본 설정으로도 취약하며 공격 성공률이 거의 100%에 달했기 때문입니다.


어떻게 해결했지?

1. 버전 업데이트

가장 우선적으로 수행한 작업은 Next.js 버전 업데이트였습니다. 또한 Next.js 버전 업데이트와 관련된 다른 라이브러리 버전 또한 체크하여 업데이트 진행했습니다.

공식 권장 패치 버전
Next.js 15.0.x → 15.0.7
Next.js 15.1.x → 15.1.11
Next.js 15.2.x → 15.2.8
Next.js 15.3.x → 15.3.8
Next.js 15.4.x → 15.4.10
Next.js 15.5.x → 15.5.9
Next.js 16.0.x → 16.0.10

2. 긴급 재배포

패치 버전으로 업데이트한 후 즉시 프로덕션 환경에 재배포했습니다. 주말이었음에도 불구하고 밤늦게까지 고생한 동료들에게 너무 감사합니다😭

3. 보안 키 점검

패치된 버전으로 업데이트를 진행하면서 서비스에서 사용중인 시크릿을 점검했습니다. 공격자가 이미 환경 변수나 시크릿에 접근했을 가능성을 배제할 수 없었기 때문입니다.

4. 외부 방화벽 도입

또한 앞으로 이런 일을 예방하기 위해 내년 초 웹 방화벽 도입을 검토 중에 있습니다. 방화벽 도입 시 서비스에 도달하기 전 네트워크 레벨에서 비정상적인 요청 패턴을 차단할 수 있어 프레임워크 취약점이 발견되더라도 한 단계 더 안전한 방어막을 구축할 수 있습니다.


느낌점

이번 React2Shell 취약점 대응을 겪어보면서 보안에 대한 인식이 많이 달라졌습니다.

평소 Next.js 블로그나 커뮤니티에서 올라오는 버전 업데이트 공지를 무심하게 지나쳤던 것을 많이 반성하게 되었습니다. "major 버전만 올리면 되지 않을까?", "보안 패치는 급하지 않겠지" 하는 안일한 생각이 얼마나 위험했던 것인지 반성하게 되었습니다.

이번 일을 계기로 Next.js의 보안 이슈 및 소식에 대해 Slack으로 즉시 알림을 받을 수 있도록 설정했습니다. 보안 패치는 공개된 순간부터 공격이 시작될 수 있기 때문에, 커뮤니티의 소식을 빠르게 캐치하는 것이 첫 번째 방어선이라는 것을 깨달았습니다.

또한 AWS 알림의 중요성도 절실히 느꼈습니다. 만약 AWS에서 메일이 오지 않았다면 서버가 다운되는 것을 훨씬 늦게 발견했을 것이고 그만큼 서비스 장애 시간도 길어졌을 것입니다. 토요일 아침이라 모니터링 대시보드를 능동적으로 확인하지 않았던 상황에서, 실시간 알림이 즉각적인 대응을 가능하게 해주었습니다. 서버 상태, 리소스 사용률, 비정상 패턴 등을 실시간으로 모니터링하고 즉각 알림받을 수 있는 시스템 구축이 얼마나 중요한지 실감했습니다.

React2Shell 취약점은 현대 웹 개발 생태계에서 얼마나 빠르게 보안 위협이 확산될 수 있는지를 깨닫게 해주었습니다. 단순히 기술적인 문제를 넘어서, 조직의 보안 대응 체계, 모니터링 시스템, 그리고 개발자의 보안 의식까지 전반적으로 점검하게 만든 계기였습니다.

우리 모두 정기적으로 확인하는 습관을 가지면 좋을 것 같습니다 🙌🏻

// 프로젝트에 설치된 npm 패키지들의 보안 취약점을 검사하는 명령어
pnpm audit

📚 참고 자료

profile
개발댕발

1개의 댓글

comment-user-thumbnail
2026년 3월 5일

아오 해커 시치!

답글 달기