8호01 / 05
Node2Shell에서 HTTP2Shell로 — Brotli 디코더 RCE가 Node를 넘어 Python·Bun·Envoy까지
이름이 사흘 동안 세 번 바뀐 취약점입니다. Node2Shell → Python2Shell → HTTP2Shell, 그리고 Broccoli2Shell. 전부 CVE-2026-111497 하나입니다.
취약점
Google Brotli C 디코더 1.0.3~1.2.0. DecodeBlockTypeAndLength()가 잘못된 스트림과 입력 부족을 구분하지 못하는 불리언만 돌려주고, 빠른 경로에서는 그 값을 무시합니다. 블록 전환이 불가능한 스트림을 받으면 디코더가 "입력이 더 필요하다"고 판단해 8바이트 내부 버퍼에 공격자 데이터를 계속 써서 범위 외 쓰기가 납니다. CWE-252, CWE-787. CVSS v4.0 9.2.
수정은 2026년 2월 Brotli 소스에 이미 들어가 있었습니다 — 당시엔 보안 취약점으로 인식되지 않았습니다. OpenAI Codex Security(Khai Tran, Sylvie Mayer)가 발견해 Node.js에 보고했습니다.
확산 경로
| 날짜 | 내용 |
|---|---|
| 10/21 | Node.js 22.23.4, 24.22.1, 26.12.1 수정. Brotli 1.0.10, 1.1.1, 1.2.1 릴리스. "Node2Shell" |
| 10/22 | NVD·GHSA 공개. Imperva Red Team이 공식 Node 24.22.0 arm64 이미지에서 코드 실행 시연(익스플로잇 비공개). 공개 PoC 등장 |
| 10/22 | Aikido: Python Brotli·brotlicffi가 같은 디코더를 컴파일 — "Python2Shell" |
| 10/23 | Bun, Envoy, Istio, 네이티브 라이브러리로 확대 — "HTTP2Shell". brotlicffi 1.2.1.0 배포 |
Node 25, 23, 20 이하는 EOL이라 수정이 없습니다.
어디가 노출되나
- 외부 URL 응답. Node
fetch(), Pythonrequests/urllib3/aiohttp/httpx는Content-Encoding: br응답을 자동 디코딩합니다. Brotli가 설치돼 있으면 앱이 import하지 않아도 호출됩니다. 악의적 서버가 br 응답을 보내면 됩니다 —Accept-Encoding에서 br을 빼도 소용없습니다. - 요청 본문. Express 5.0.0
5.3.0과 body-parser 2.0.02.3.0은 br 요청 본문을 디코딩합니다. Express 자체 결함은 아니라 Express 업그레이드로는 안 됩니다. - 직접 호출.
zlib.brotliDecompress*()등.
Apache·Nginx 기본 설정은 요청을 br 디코딩하지 않아 해당하지 않습니다. 순수 Node HTTP 서버도 코드가 디코더를 부르지 않으면 안전합니다.
악용 현황
Imperva가 코드 실행에 성공했지만 여러 번 시도가 필요했고 익스플로잇은 공개하지 않았습니다. 공개 PoC는 일부러 약화한 빌드에서만 코드 실행에 닿고 표준 빌드에서는 크래시와 제한적 메모리 읽기입니다. Python 쪽은 ASan으로 확인만 했습니다. 10월 24일 기준 실제 공격 보고는 없습니다. 신뢰할 만한 비공개 익스플로잇이 있다는 언급은 있습니다.
아직 안 고쳐진 곳
.NET, PHP, Ruby, DuckDB, ClickHouse, Apache Arrow, MuPDF, 7-Zip 계열의 번들 복사본은 10월 24일 기준 미수정으로 보고됐습니다. 벤더 advisory를 봐야 합니다.
실무에서 할 일
Node: 22.23.4 / 24.22.1 / 26.12.1로. 공식 우회책은 없습니다.
Python: pip list | grep -i brotli — 있으면 Brotli>=1.2.1, brotlicffi>=1.2.1.0. 못 올리면 제거하세요(httpx[brotli] 같은 extra도). urllib3·requests·aiohttp는 gzip·deflate로 넘어갑니다. pip-audit가 처음에 못 잡았다는 보고가 있으니 직접 보세요.
공통: 프로세스 재시작, 이미지 재빌드, lockfile 갱신. 프록시·WAF에서 Content-Encoding: br 요청 본문 차단. 단, 앱이 밖으로 가져오는 응답은 WAF가 못 봅니다 — 그쪽은 패치만이 답입니다.
이후 이어진 소식
8호의 다른 글
요약으로 한 번에 보기 →- 01Node2Shell에서 HTTP2Shell로 — Brotli 디코더 RCE가 Node를 넘어 Python·Bun·Envoy까지지금 읽는 글
- 02macOS의 git·curl·python3는 아직 eMudhra 인증서를 믿는다 — 통보 11일째, 27.2 업데이트가 수동 조치를 되돌렸다
- 03Tailscale SSH 'Tailworm' — 패치 전 공개된 11건, 포워딩 경로로 루트와 등록 키까지
- 04CPython 실험적 JIT, 본선에서 빠진다 — PEP 836 철회, '끌고 갈 여력이 없다'
- 05Claude Code가 백그라운드 에이전트 전사를 30초마다 모델에 보낸다 — 상태 줄 다섯 단어에 지출의 16%
2026년 10월 24일에 올라온 글
그날 대시보드 →이날은 이 글 하나입니다.
댓글
불러오는 중…