압축 데이터 하나로 서버를 노리는 Node.js 취약점, Node2Shell이란 무엇인가?
PHP2Shell에 이어 이번에는 Node.js에서 조작된 압축 데이터만으로 서버를 멈추거나 장악할 수 있는 취약점(Node2Shell)이 공개됐습니다. 패치 다음 날 공격 코드(PoC)가 공개됐고, 지원이 끝난 Node.js 20 등은 공식 패치가 없습니다. 무엇이 문제이고, 무엇부터 해야 하는지 정리했습니다.

목차
ㄴ 무슨 일이 있었나
ㄴ 주요 경과
ㄴ 쉽게 이해하기
ㄴ 왜 중요한가
ㄴ 오해와 사실
ㄴ 현장에서 보면
ㄴ 이렇게 대비하세요
ㄴ 용어 풀이
ㄴ 관련기사(출처)
ㄴ 누구나 이용할 수 있는 Node.js 무료 점검
□ 무슨 일이 있었나
Node.js 개발팀은 2026년 10월 21일 보안 릴리스를 배포하고, 내장된 Brotli(브로틀리) 압축 해제 기능에서 원격 코드 실행으로 이어질 수 있는 취약점(CVE-2026-111497)을 고쳤습니다.
이 취약점은 연구자들 사이에서 'Node2Shell'로 불립니다. Node.js는 위험도를 '높음(High)'으로 분류했고, 원천 라이브러리 관리 주체인 구글은 CVE 기록에서 CVSS v4.0 9.2점을 매겼습니다.
패치 다음 날인 10월 22일 공개 PoC가 등장했고, 보안업체 임퍼바(Imperva)는 공식 배포판 Node.js에서 원격 코드 실행을 재현했다고 밝혔습니다. 다만 10월 23일 기준 실제 공격 사례는 보고되지 않았습니다.
1. 취약점 : CVE-2026-111497 (통칭 Node2Shell)
2. 유형
- Brotli 디코더 경계 밖 쓰기(Out-of-bounds Write)
- 서비스 중단(크래시), 메모리 정보 노출, 조건부 원격 코드 실행(RCE)
3. 심각도
- Node.js 공식 등급 높음(High) / 구글 CVE 기록 CVSS v4.0 9.2
4. 수정 버전
- Node.js 22.23.4 / 24.22.1 / 26.12.1 이상 (Bun은 1.4.4)
5. 영향 버전
- 위 수정 버전 미만의 22.x·24.x·26.x
- 지원 종료된 20.x 이하와 21·23·25.x도 영향 → 공식 패치 없음
□ 주요 경과
- 시점 미공개
. OpenAI Codex Security 연구진이 Node.js에 취약점 보고
- 2026년 10월 21일
. Node.js, 22.23.4 / 24.22.1 / 26.12.1 보안 릴리스 배포 (같은 릴리스에서 다른 높음 등급 취약점도 함께 수정)
. 원천 라이브러리 구글 Brotli도 1.0.10 / 1.1.1 / 1.2.1에서 수정
- 2026년 10월 22일
. 첫 공개 PoC 등장 (크래시·메모리 노출 재현, 일부 환경에서 불안정한 코드 실행)
. 임퍼바, 공식 Node.js 24.22.0(Linux arm64)에서 원격 코드 실행 재현 및 WAF 차단 규칙 적용
. 자바스크립트 런타임 Bun, 1.4.4에서 동일 결함 수정
- 2026년 10월 23일
. 티오리(Xint), 직접 재현·검증한 국내 대응 가이드 공개
. 미국 CISA 악용 취약점 목록(KEV) 미등재, 실제 공격 보고 없음
- 진행 중
. 국내 보안·개발 기업들, 무료 점검 서비스 공개
□ 쉽게 이해하기
웹에서 주고받는 데이터는 크기를 줄이려고 '압축 포장'해서 보내는 경우가 많고, Brotli는 그 포장 방식 중 하나입니다. Node.js 안에는 이 포장을 푸는 자동 개봉기(디코더)가 들어 있습니다.
공격자는 포장 안내문을 일부러 엉터리로 적은 소포를 보냅니다. 정상 개봉기라면 "이상한 소포"라며 작업을 멈춰야 하는데, 패치 전 개봉기는 그대로 계속 풀다가 정해진 작업대 밖까지 내용물을 쏟아 버립니다. 이 틈으로 서버가 멈추거나, 메모리 정보가 새거나, 특정 조건에서는 공격자 명령이 실행될 수 있습니다.
소포가 들어오는 길은 두 가지입니다.
- 들어오는 길 : 사용자가 보낸 압축 요청을 서버가 자동으로 푸는 경우 (Express 5 등)
- 나가서 받아오는 길 : 서버가 외부 API·웹훅·URL에서 받아온 압축 응답을 자동으로 푸는 경우 (fetch(), axios 등)
PHP2Shell과 달리 Node.js를 쓴다는 사실만으로 바로 공격이 되지는 않습니다. 패치 안 된 디코더 + 공격자 데이터가 디코더까지 가는 길이 함께 있어야 합니다.
□ 왜 중요한가
1. 모르는 사이에 노출돼 있을 수 있습니다
- 코드에서 Brotli를 직접 쓰지 않아도 Express 5의 요청 본문 처리, Node.js 기본 fetch(), axios·got·undici 같은 HTTP 클라이언트가 자동으로 압축을 풉니다.
- 외부 API 연동, 웹훅 수신, 외부 이미지·피드 가져오기처럼 서버가 바깥 응답을 읽는 모든 기능이 진입점이 될 수 있습니다.
2. 공격 준비가 빨라졌습니다
- 로그인 없이 압축 데이터만으로 공격이 시도될 수 있고, 패치 하루 만에 공개 PoC가 나왔습니다.
- Node.js 공식 권고에는 런타임 안에서 쓸 수 있는 우회책이 없어, 업데이트가 사실상 유일한 해결책입니다.
3. 지원 종료 버전은 패치가 없습니다
- Node.js 20.x는 2026년 4월 30일 지원이 끝나 공식 수정이 나오지 않습니다. 아직 20.x로 운영 중인 서비스는 지원 버전으로 옮겨야 합니다.
□ 오해와 사실
| 이런 말이 돌지만 | 사실은 |
| 우리는 Brotli를 안 쓰니 괜찮다 | Express 5, fetch(), 주요 HTTP 클라이언트가 자동으로 압축을 풉니다. 코드에 Brotli가 없어도 디코더는 동작할 수 있습니다. |
| npm 패키지만 업데이트하면 된다 | 결함은 Node.js 런타임에 내장된 디코더에 있습니다. Node.js 자체를 수정 버전으로 올려야 합니다. |
| Express 4라서 상관없다 | Express 4의 요청 본문은 Brotli를 거부하지만, 서버가 fetch()·axios 등으로 외부 응답을 받는 경로는 여전히 해당될 수 있습니다. |
| Node.js 20은 LTS니까 곧 패치가 나온다 | 20.x는 2026년 4월 30일 지원이 끝나 공식 패치가 없습니다. |
| PHP2Shell처럼 이미 공격이 쏟아지고 있다 | 10월 23일 기준 실제 공격 보고와 CISA KEV 등재는 없습니다. 다만 공개 PoC가 있어 시간 문제로 보는 게 맞습니다. |
| 무료 점검에서 문제가 없으면 안전하다 | URL 점검은 외부에서 보이는 경로만 봅니다. 사내 전용 서비스, 배치·워커처럼 URL이 없는 Node.js는 서버에서 직접 확인해야 합니다. |
□ 현장에서 보면
Node.js는 보안팀 자산 목록에 잘 안 잡히는 곳에 숨어 있습니다. 화면 뒤의 API 중계 서버, 챗봇·알림·웹훅 연동 서버, 사내 업무 도구, 그리고 컨테이너 이미지 안이 대표적입니다. 서버에서node -v를 확인했어도 실제 서비스는 컨테이너 속 다른 버전으로 돌고 있는 경우가 흔합니다.
이번 건은 "밖에서 들어오는 요청"보다 "우리가 밖에서 받아오는 응답"이 더 놓치기 쉽습니다. 외부 API를 부르는 서버는 방화벽 안쪽에 있어도 공격 데이터를 스스로 받아올 수 있습니다. 업데이트 후 PM2·systemd 프로세스 재시작, 컨테이너 재빌드까지 끝나야 '조치 완료'입니다.
□ 이렇게 대비하세요
1. 개인 사용자 / 소규모 사업자
- 외주로 만든 웹서비스·앱 서버가 Node.js 기반이라면 제작·유지보수 업체에 Node.js 버전과 조치 여부를 확인하세요.
- 클라우드·호스팅 서비스를 쓴다면 런타임 버전 설정이 수정 버전 이상인지 확인하세요.
- 개발자라면 개인 PC의 Node.js도 함께 업데이트하세요. 개발 도구도 외부 응답을 받아 압축을 풉니다.
2. 기업 - 기술적 조치
- [1순위] 업데이트 후 재시작 : 22.23.4 / 24.22.1 / 26.12.1 이상 적용 후 프로세스 재시작 (PM2·systemd는 바이너리를 바꿔도 기존 프로세스가 그대로 돎)
- 컨테이너 : 베이스 이미지 재빌드·재배포, node:22-alpine 같은 이동 태그를 믿지 말고 새 이미지 안에서 버전 재확인
- 패치 여부 확인 : node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH ?? 'ABSENT'" → -17이면 패치, ABSENT면 미패치 (배포판의 공유 라이브러리 빌드는 libbrotli 패키지 버전도 함께 확인)
- 지원 종료 버전(20.x 이하, 21·23·25.x) : 배포판·LTS 지원 업체 보안 업데이트 확인 후 지원 버전으로 이전
- 패치 전 임시 완화 : 리버스 프록시(nginx 등)에서 Content-Encoding: br 요청 본문 차단(415 응답), 애플리케이션에서 막을 경우 body-parser보다 앞단에 배치 (express.json inflate 끄기는 gzip까지 막혀 비권장)
- WAF : 사용 중인 WAF의 Node2Shell 규칙 적용 여부 확인 (보조 수단)
3. 기업 - 관리적 조치
- 자산 파악 : 호스트뿐 아니라 컨테이너 이미지 내부의 Node.js 버전까지 목록화 (Bun 런타임 포함)
- 우선순위 : ① 웹훅·외부 API 연동 등 외부 응답을 읽는 서비스 → ② Express 5 등 압축 요청 본문을 받는 서비스 → ③ 그 외
- 침해 시도 점검
· 평소 거의 없는 Brotli 압축 해제 오류가 갑자기 늘었는지 (패치 전 런타임은 ERR__ERROR_FORMAT_BLOCK_LENGTH_1 등으로 기록)
· 원인 모를 워커 재시작·메모리 초과(OOM)·segfault, br 압축 요청 직후 응답 지연 반복
- 협력사 확인 : 외주·솔루션·SaaS 벤더에 Node.js 사용 여부와 조치 결과를 문서로 회신받기
□ 용어 풀이
- Node.js : 자바스크립트로 서버 프로그램을 만들고 실행하는 환경. 웹 API, 챗봇, 실시간 서비스 등에 널리 사용
- Brotli(브로틀리) : 구글이 만든 데이터 압축 방식. 웹 전송량을 줄이는 데 쓰임
- 디코더 : 압축된 데이터를 원래대로 푸는 기능
- 경계 밖 쓰기(Out-of-bounds Write) : 정해진 메모리 공간 밖에 데이터를 써 버리는 결함. 원격 코드 실행으로 이어질 수 있음
- Express / body-parser : Node.js의 대표 웹 프레임워크와 요청 본문 처리 기능
- fetch() : 서버가 외부 주소에서 데이터를 받아오는 기본 기능
- PoC : 취약점이 실제로 동작함을 보여주는 공격 시연 코드
- CISA KEV : 미국 사이버보안청이 관리하는 '실제 악용이 확인된 취약점' 목록
- EOL(지원 종료) : 제조사가 더 이상 보안 업데이트를 내지 않는 상태
□ 관련기사(출처)
- October 2026 Security Releases - Node.js 공식
- Node2Shell (CVE-2026-111497) 긴급 대응 방안 - Xint(티오리)
- [긴급] PHP2Shell 이어 이번엔 ‘Node2Shell’…Node.js 치명적 취약점, 인증 없이 서버 장악 위험 - 데일리시큐
- Researchers Demonstrate Node2Shell RCE Exploit on Node.js Build Using Crafted Brotli Data - The Hacker News
- Node2Shell: From Brotli Data to Remote Code Execution - Imperva
- CVE-2026-111497 (Node2Shell): Node.js Brotli RCE, EOL Risk - HeroDevs
- Patch Your Node and Eat Your Brotli - Semgrep
- Node.js v22.23.4 릴리스 노트 - GitHub
□ 누구나 이용할 수 있는 Node.js 무료 점검
※ 반드시 본인이 관리하거나 점검 권한을 받은 사이트만 점검하세요. 남의 사이트를 무단으로 점검하면 법적 문제가 될 수 있습니다.
※ URL 점검은 외부에서 접근 가능한 경로만 확인합니다. 사내 전용 서비스, 외부 API를 부르기만 하는 서버, 배치·워커처럼 URL이 없는 Node.js는 서버에서 직접 확인해야 합니다.
| 서비스 | 제공 | 이용 방법 | 이런 분께 |
| Node2Shell Scanner (Node.js Guard) | 티오리(Xint) | https://를 포함한 서비스 URL 입력, 도메인·API 주소별로 각각 점검 | Node2Shell 노출 가능성을 바로 확인하려는 분 |
| 무료 웹사이트 보안 진단 | 넥시얼(NEXIAL) | URL 입력, HTTPS·보안 헤더·쿠키·서버 정보 노출 등 6개 항목 점검 | 웹사이트 기본 보안 설정을 함께 점검하려는 분 (Node.js 버전은 응답에 노출된 경우만 확인, 취약 여부는 확정하지 않음) |
서버 관리자라면 한 줄로 직접 확인
- node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH ?? 'ABSENT'"
- 결과가 -17이면 패치됨, ABSENT면 미패치 (실제 서비스가 도는 서버·컨테이너 안에서 실행)
점검 결과 이렇게 보세요
- 취약·미패치 : 즉시 업데이트 → 프로세스 재시작(컨테이너 재빌드) → 압축 해제 오류·워커 재시작 로그 점검
- 확인 불가 : 서버·컨테이너 안에서 직접 버전 확인 (외주·호스팅 이용자는 업체 문의)
- 안전(패치됨) : URL이 없는 내부 Node.js 서비스도 빠짐없이 확인했는지 점검
- 인터넷에 "Node2Shell PoC"로 도는 출처 불명 공격 코드는 악성코드가 섞여 있을 수 있으니 실행하지 마세요.
감사합니다.