GN⁺: HTTP/2 연속성 홍수: 기술적 세부 사항
(nowotarski.info)HTTP/2 CONTINUATION
Flood 취약점: 기술적 세부 사항
-
CONTINUATION
Flood는 여러 HTTP/2 프로토콜 구현에서 발견된 취약점 범주로, Rapid Reset 공격보다 더 심각한 위협을 제기함. - 공격으로 인한 결과는 서버 충돌부터 성능 저하에 이르기까지 다양하며, 공격 요청은 HTTP 접근 로그에 나타나지 않음.
서문
- 2023년 10월 HTTP/2 Rapid Reset 공격에 대해 알게 되었고, HTTP/2에 대한 보안 분석 관점에서 연구를 시작하기로 결정함.
HTTP/2에 대한 간단한 소개
- HTTP/1.1과 HTTP/2의 주요 차이점은 후자가 이진 프로토콜이며, 클라이언트와 서버가 텍스트 라인 대신 _프레임_을 교환한다는 것임.
-
HEADERS
프레임과CONTINUATION
프레임에 대한 설명이 필요함.
HEADERS
프레임
-
HEADERS
프레임은 요청과 응답의 HTTP 헤더를 전송하는 데 사용되며,HPACK
인코딩 알고리즘을 사용하여 헤더 데이터를 압축함. - 프레임에는
END_HEADERS
와END_STREAM
과 같은 플래그가 설정될 수 있음.
CONTINUATION
프레임
-
CONTINUATION
프레임은HEADERS
프레임과 매우 유사하지만END_HEADERS
플래그만 가지며, 이 플래그가 설정되면 헤더 스트림이 끝났음을 의미함.
CONTINUATION
Flood 취약점
- 클라이언트가 새로운 HTTP/2 스트림을 시작하고
HEADERS
와CONTINUATION
프레임을 보내지만END_HEADERS
플래그가 절대 설정되지 않는 경우, 서버는 무한한 헤더 스트림을 분석하고 메모리에 저장해야 함. - HTTP/1.1에서는 헤더 크기 제한과 요청/헤더 타임아웃으로 무한 헤더로부터 보호되지만, 많은 HTTP/2 서버에서 이러한 보호 조치가 누락되거나 잘못 구현되었음.
CPU 소모: Golang 사례
- Golang은
CONTINUATION
Flood로 인한 CPU 소모의 예로,http2MetaHeadersFrame
이라는 추상 클래스를 사용하여HEADERS
프레임과CONTINUATION
프레임을 처리함. - HPACK 디코더는 헤더 크기 제한에 도달하면 헤더 방출을 중단하도록 설정되어 있지만,
END_HEADERS
플래그가 없으면 함수가 반환되지 않고 계속 헤더를 디코딩함.
메모리 부족
- 메모리 부족은 가장 심각한 케이스 중 하나로,
CONTINUATION
프레임을 사용하여 구축된 헤더 목록의 크기를 제한하지 않는 구현이 있음. - 헤더 타임아웃이 없는 구현에서는 단일 HTTP/2 연결만으로 서버를 충돌시킬 수 있음.
달성 가능한 단언문 충돌: Node.js (특별한 경우)
- Node.js는
CONTINUATION
프레임의 무한 스트림을 적절히 처리하지만, 헤더 스트림 도중 연결이 끊어질 때 데이터 경쟁 버그가 발생함. - Node.js는
Http2Session
소멸자 내에서 메모리 할당을 추적하고, 연결이 끊어질 때current_nghttp2_memory_
값이 동시에 업데이트되어 충돌이 발생할 수 있음.
이전 HTTP/2 취약점과의 비교
- 과거에는 여러 HTTP/2 취약점이 보고되었으며,
CONTINUATION
Flood는 이전 취약점들과 다른 방식으로 작동함. -
CONTINUATION
Flood는 비어 있는 헤더를 보내는 대신 서버에 의해 설정된 프레임 크기 제한까지 많은 임의의 헤더를 보냄.
최종 비고
- HTTP/2 트래픽은 모든 인간 HTTP 트래픽의 약 60%를 차지하며, 영향을 받는 프로젝트의 중요성을 고려할 때 인터넷의 상당 부분이 쉽게 악용될 수 있는 취약점에 영향을 받았음.
- 이 취약점이 야생에서 악용되었다면, 서버 관리자가 적절한 HTTP/2 지식 없이는 디버깅하기 매우 어려웠을 것임.
GN⁺의 의견
- 이 취약점은 서버의 가용성을 심각하게 저해할 수 있으며, 특히 로그에 기록되지 않기 때문에 추적과 대응이 어려움.
- 서버 관리자는 정기적으로 보안 업데이트를 적용하고, 트래픽 분석 도구를 사용하여 비정상적인 패턴을 감지해야 함.
- 이러한 취약점은 사이버 보안 커뮤니티에 경각심을 일으키고, 보다 안전한 프로토콜 설계와 구현의 중요성을 강조함.
- 비판적으로 볼 때, 이 취약점은 널리 사용되는 프로토콜의 기본 설계 결함을 드러내며, 이는 인터넷의 기본 인프라에 대한 신뢰성 문제를 제기함.
- 관련 분야의 지식을 가진 전문가가 아니라면, 이와 같은 복잡한 취약점을 이해하고 대응하는 것이 어려울 수 있으므로, 보안 교육과 인식 향상이 필요함.
Hacker News 의견
-
해당 이슈를 최근에 Bandit에서 해결함
- 한 달 전 Bandit에서 같은 문제를 해결했다는 개인적인 경험.
- 링크를 통해 구체적인 코드 위치 제공.
- 구현자의 관점에서 이 문제는 매우 명백하며, 다른 구현체들도 이미 방어책을 마련했을 것으로 생각했음.
- 그러나 수십 개의 구현체를 확인한 결과, 심지어 주요 HTTP/2 서버들에서도 이러한 보호 장치가 없거나 잘못 구현되어 있었음.
-
개발 문화에 대한 비판
- 개발자들이 자동으로 동적으로 확장되는 것에 너무 익숙해져서, 어떤 것이 얼마나 커질 수 있는지에 대해 생각하지 않는 문화가 문제라고 지적.
- 이러한 문제는 HTTP/2에만 국한되지 않지만, HTTP/2의 복잡성이 문제를 더욱 악화시킬 수 있음.
- 과거 HTTP/1.x 시절에는 C 같은 언어를 사용하며 버퍼 길이 관리에 지속적인 주의가 필요했고, 요청 헤더 할당을 무한정 확장하는 일은 없었음.
-
영향을 받지 않는 서버/리버스 프록시 목록
- 이전 기사에서 언급된 영향을 받지 않는 웹 서버 및 리버스 프록시 목록.
- Nginx, Jetty, HAProxy, NetScaler, Varnish 등이 영향을 받지 않음.
-
HTTP/1.1의 안전성에 대한 고민
- 저희 사이트가 하루 종일 주목을 받았다고 언급.
- 저희 사이트의 트래픽이 적은 경우, HTTP/1.1을 사용하는 것이 더 안전한지에 대한 의문 제기.
-
저자에 대한 칭찬
- 저자가 넓은 시야로 접근하고, 발견한 내용을 책임감 있게 보고하며, 읽기 쉬운 방식으로 공유한 것에 대한 칭찬.
-
Slowloris v2에 대한 언급
- 이 문제를 천천히 발생시키면 'slowloris v2'라고 부를 수 있을 것이라는 농담.
-
오타에 대한 언급
- 'serveral retries'라는 오타를 재미있어 함.
-
HTTP/2에 대한 비판적인 시각
- HTTP/2를 어떻게 애플리케이션 계층 프로토콜에 '업그레이드'를 위한 전송 계층으로 밀어넣을 수 있는지에 대한 비판.