스크랩

Brotli 압축 해제 버그가 원격 코드 실행으로: Node·Python·.NET을 흔드는 'http2shell' 정리

Brotli 압축 해제 버그가 원격 코드 실행으로: Node·Python·.NET을 흔드는 'http2shell' 정리

한눈에 보기

최근 http2shell이라는 이름의 취약점이 개발자 커뮤니티에서 화제가 되고 있습니다. 문제의 원인은 Google이 만든 압축 라이브러리 Brotli의 C 참조 구현입니다. 이 구현의 디코더에서 범위를 벗어난 메모리 접근(out-of-bounds) 이 발생하고, 조건에 따라 원격 코드 실행(RCE) 으로 이어질 수 있다는 것이 핵심입니다.

  • 영향 범위: Brotli 1.2.0 이하
  • 영향받는 생태계: Node.js, Python(brotli 패키지), .NET(Microsoft의 Brotli 모듈은 Google 참조 구현의 바인딩), libcurl을 통해 Brotli를 링크하는 프로그램 등
  • 조치: Python brotli 패키지는 이미 1.2.1로 업데이트됐고, Node도 패치 릴리스가 나왔습니다

이 글에서는 GeekNews에 소개된 Hacker News 토론을 바탕으로 핵심 내용과 쟁점을 정리했습니다.


왜 문제가 되나요?

HTTP 응답은 Content-Encoding: br 헤더를 붙여 Brotli로 압축해 보낼 수 있습니다. 이런 응답을 받은 클라이언트 라이브러리가 자동으로 압축을 풀도록 설정돼 있다면, 공격자는 조작한 압축 데이터를 보내는 것만으로 디코더의 메모리 버그를 건드릴 수 있습니다.

한 사용자는 Python에서 httpx.get(URL) 한 줄만으로 충돌을 재현했다고 밝혔습니다. 다만 ASLR 우회까지는 성공하지 못해, 실제로 동작하는 RCE 익스플로잇을 만드는 데는 이르지 못했다고 덧붙였습니다.

생각보다 넓은 의존성 사슬

  • Python brotli 패키지는 aiohttp[speedups], urllib3[brotli] 같은 선택 의존성으로도 함께 설치됩니다. 그래서 이름조차 모른 채 쓰고 있는 경우가 많을 수 있습니다.
  • Rust의 순수 구현 brotli 크레이트는 C 바인딩이 아니어서 이번 버그와 직접 관련은 없어 보입니다. 하지만 libcurl을 통해 시스템의 libbrotlidec을 동적 링크하는 크레이트(예: curl, isahc 기반 프로젝트)는 점검이 필요하다는 지적이 나왔습니다.

커뮤니티의 주요 쟁점

1. 위험이 과장된 걸까, 실제로 심각한 걸까?

의견이 크게 엇갈렸습니다.

  • 신중론: Node, Python, C# 저장소 200여 개를 확인했더니 서버 측에서 Brotli 디코더를 실제로 호출하는 곳이 없었다고 합니다. 이 플랫폼들은 서버에서 요청 본문을 Brotli로 자동 해제하는 기능을 기본으로 켜지 않기 때문이라는 설명입니다. 클라이언트는 공격자 서버에 접속해야만 공격받으니, 밤을 새워 고칠 정도는 아니라는 의견입니다.
  • 경계론: 서버라도 외부 URL을 가져오는 코드(크롤러, 웹훅, AI 에이전트의 웹 검색 등)가 있으면 사실상 클라이언트 역할을 합니다. 예를 들어 Node의 fetch는 br 응답을 자동으로 디코딩하므로, 서버가 가져오는 콘텐츠를 공격자가 통제할 수 있다면 위험하다는 반론이 나왔습니다.

정리하면, '외부 HTTP 응답을 자동으로 압축 해제하는 코드가 있는가' 가 실제 위험을 가르는 기준입니다.

2. 수정은 2월에 끝났는데, 릴리스는 왜 늦었나

흥미로운 점은 Brotli 저장소에 수정 커밋이 이미 올해 2월에 들어가 있었다는 것입니다. 하지만 당시에는 보안 수정으로 인식되지 않아 별도 릴리스가 나오지 않았습니다. 이후 OpenAI의 에이전트가 이 커밋의 보안상 의미를 찾아냈다고 OpenAI가 밝혔습니다.

일부 사용자는 Google이 내부에서는 main 브랜치로 빌드하기 때문에 영향을 받지 않았지만, 오픈소스 릴리스는 1년 가까이 나오지 않은 채 수정 커밋 100개 이상이 쌓여 있었다고 비판했습니다.

3. 결국 메모리 안전성 문제

토론에서 가장 많이 나온 결론은 '또 C 코드의 범위 밖 메모리 접근' 이었습니다.

  • 압축 해제 코드는 비교적 구현이 쉽고 외부 입력에 직접 노출되므로, 메모리 안전한 언어로 작성하는 것이 마땅하다는 의견이 많았습니다.
  • Rust 등 메모리 안전성을 적극 장려해 온 Google이 정작 이런 버그를 냈다는 점도 비판받았습니다.
  • 반대로 Rust 생태계도 C 라이브러리 바인딩을 통해 얼마든지 영향받을 수 있다는 점이 함께 지적됐습니다.

4. 취약점에 '이름' 붙이기, 이대로 괜찮을까

메모리 버그마다 그럴듯한 이름을 붙여 홍보하는 관행에 피로감을 느낀다는 의견도 있었습니다. 허리케인처럼 NIST가 이름 목록을 만들어 CVSS 9.0 이상 취약점에만 순서대로 붙이자는 재치 있는 제안도 나왔습니다.


지금 바로 확인할 것 체크리스트

  1. Brotli 버전 확인: 시스템 라이브러리(libbrotlidec)와 언어별 패키지가 1.2.0 이하인지 확인하세요.
  2. Python: pip show brotli로 버전을 확인하고 1.2.1 이상으로 올리세요. aiohttp[speedups], urllib3[brotli]를 통해 간접 설치된 경우도 꼭 확인하세요.
  3. Node.js: 보안 패치가 반영된 최신 릴리스로 업데이트하세요. 특히 fetch로 외부 URL을 가져오는 서버라면 우선순위를 높이세요.
  4. .NET: Microsoft Brotli 모듈의 패치 여부를 확인하세요.
  5. libcurl 기반 도구·라이브러리: OS 패키지 업데이트로 시스템 Brotli를 갱신하세요.
  6. 외부 콘텐츠를 가져오는 서비스 우선 점검: 크롤러, 링크 미리보기, 웹훅, AI 에이전트 도구 등이 대상입니다.

마치며

http2shell 자체의 실제 파급력은 아직 논쟁 중입니다. 하지만 이번 사건은 몇 가지 교훈을 분명하게 남겼습니다.

  • 보안 수정으로 인식되지 못한 커밋이 몇 달 동안 릴리스되지 않을 수 있다
  • AI 에이전트가 이런 숨은 취약점을 찾아내는 시대가 이미 왔다
  • 외부 입력을 다루는 C 코드는 여전히 가장 큰 공격 표면이다

한 댓글처럼 '인터넷에서 접근 가능한 C 코드가 남아 있는 한' 이런 일은 계속될 것입니다. 그러니 의존성 업데이트를 일상적인 습관으로 만들어 두는 것이 가장 현실적인 대비책입니다.


원문: https://news.hada.io/topic?id=35909