이 블로그 게시물에서는 최근 발견된 HTTP/2 프로토콜 관련 취약점을 중점적으로 다룹니다. 특정 조건에서 이 취약점이 악용되면 HTTP/2 사양의 서버 측 부분을 구현하는 NGINX Open Source, NGINX Plus 및 관련 제품을 대상으로 서비스 거부 공격이 실행될 수 있습니다. 이 공격으로부터 시스템을 보호하려면 NGINX 구성을 즉시 업데이트하는 것이 좋습니다.
HTTP/2 스트림 재설정의 문제점
서버와 연결을 설정한 후 HTTP/2 프로토콜을 사용하면 클라이언트가 데이터 교환을 위한 여러 스트림을 동시에 시작할 수 있습니다. 이전 버전의 프로토콜과 달리, 최종 사용자가 페이지를 벗어나거나 다른 이유로 데이터 교환을 중단하려는 경우 HTTP/2는 스트림을 취소하는 방법을 제공합니다. 서버에 RST_STREAM 프레임을 전송하여 불필요한 작업이 실행되지 않도록 합니다.
이 취약점은 이미 설정된 연결을 통해 다수의 HTTP/2 스트림을 시작한 후 빠르게 취소하여 서버의 최대 동시 스트림 수 제한을 우회하는 방식으로 악용됩니다. 이는 들어오는 스트림이 후속 스트림의 도착 속도보다 빠르게 재설정되기 때문에 발생하며, 클라이언트는 설정된 임계값에 도달하지 않고도 서버에 과부하를 일으킬 수 있습니다.
NGINX에 미치는 영향
성능 및 리소스 사용량을 고려하여 NGINX는 동시 스트림 수를 기본적으로 128개로 제한합니다(참조: http2_max_concurrent_streams). 또한 네트워크와 서버 성능 간의 균형을 최적화하기 위해 NGINX는 HTTP keepalive를 사용하여 클라이언트가 기본적으로 최대 1,000개의 요청까지 HTTP 연결을 유지할 수 있도록 합니다(참조: keepalive_requests).
NGINX는 기본 keepalive 제한을 적용하여 이러한 유형의 공격을 방지합니다. 이 제한을 우회하기 위해 추가 연결을 생성하면 표준 레이어 4 모니터링 및 경고 도구를 통해 악의적 행위자가 드러납니다.
그러나 NGINX의 keepalive가 기본값 및 권장 설정보다 훨씬 높게 구성된 경우, 공격으로 인해 시스템 리소스가 고갈될 수 있습니다. 스트림 재설정이 발생하면 HTTP/2 프로토콜은 해당 스트림에서 이후의 데이터가 클라이언트로 반환되지 않도록 요구합니다. 일반적으로 재설정으로 인해 발생하는 서버 오버헤드는 취소를 정상적으로 처리하는 작업 정도로 미미합니다. 그러나 NGINX의 스트림 임계값을 우회하면 클라이언트가 이러한 오버헤드를 악용하여 수천 개의 스트림을 빠르게 시작함으로써 그 영향을 증폭할 수 있습니다. 이로 인해 서버 CPU 사용량이 급증하여 정상적인 클라이언트에 대한 서비스가 거부됩니다.
비정상적으로 높은 keepalive 제한에서 HTTP/2 스트림을 설정한 후 스트림을 취소하여 발생하는 서비스 거부 공격.
공격 노출 위험을 완화하기 위한 단계
완전한 기능을 갖춘 서버이자 프록시인 NGINX는 관리자가 서비스 거부 공격을 완화할 수 있는 강력한 도구를 제공합니다. 이러한 기능을 활용하려면 NGINX 구성 파일을 다음과 같이 업데이트하여 서버의 공격 표면을 최소화해야 합니다:
- keepalive_requests는 기본 설정인 요청 1,000회로 유지해야 합니다
- http2_max_concurrent_streams은(는) 기본 설정인 128개 스트림으로 유지해야 합니다
또한 모범 사례로 다음과 같은 안전 조치를 추가할 것을 권장합니다:
- limit_conn은 단일 클라이언트에서 허용되는 연결 수를 제한합니다. 애플리케이션 성능과 보안 간의 균형을 고려하여 이 지시문에 적절한 값을 설정해야 합니다.
- limit_req는 단일 클라이언트에서 일정 시간 동안 처리되는 요청 수를 제한합니다. 이 지시어는 애플리케이션 성능과 보안 간의 균형을 고려하여 적절한 값으로 설정해야 합니다.
당사의 대응 방안
당사는 여러 완화 전략을 실험하여 이 공격이 다양한 고객과 사용자에게 어떤 영향을 미칠 수 있는지 파악했습니다. 이번 연구를 통해 NGINX에는 이미 공격을 방지하는 데 필요한 모든 도구가 갖춰져 있음을 확인했지만, 권장 사양을 넘어 NGINX를 구성해야 하는 사용자도 그렇게 할 수 있도록 추가 조치를 취하고자 했습니다.
조사 결과, HTTP/2 프로토콜에서 이론적으로 발생할 수 있는 다양한 형태의 플러드 공격에 대한 서버 복원력을 향상하는 방법을 찾아냈습니다. 이에 따라 이러한 상황에서 시스템 안정성을 높이는 패치를 배포했습니다. 이러한 위협으로부터 보호하기 위해 NGINX Open Source 사용자는 최신 코드베이스로 바이너리를 다시 빌드하고, NGINX Plus 고객은 즉시 최신 패키지(R29p1 또는 R30p1)로 업데이트할 것을 권장합니다.
패치 작동 방식
NGINX에 대한 플러드 공격을 조기에 탐지할 수 있도록, 이 패치는 하나의 이벤트 루프 내에서 새로 생성할 수 있는 스트림 수를 제한합니다. 이 제한은 http2_max_concurrent_streams 지시문을 사용하여 구성한 값의 두 배로 설정됩니다. 요청을 보낸 직후 스트림이 재설정되는 경우(이번 공격 사례처럼)와 같이 최대 임계값에 도달하지 않더라도 이 제한이 적용됩니다.
영향을 받는 제품
이 취약점은 NGINX HTTP/2 모듈(ngx_http_v2_module)에 영향을 미칩니다. 영향을 받을 수 있는 특정 NGINX 또는 F5 제품에 대한 자세한 내용은 다음 페이지를 참조하십시오: https://my.f5.com/manage/s/article/K000137106.
CVE-2023-44487 – HTTP/2 Rapid Reset 공격에 대한 자세한 내용은 다음을 참조하세요: https://www.cve.org/CVERecord?id=CVE-2023-44487
감사의 말
이 취약점을 발견하고 식별 및 완화하기 위해 협력해 주신 Cloudflare, Amazon, Google에 감사드립니다.
관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.