HTTP/2 다운그레이드에서의 요청 스머글링

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

HTTP/2는 일반적으로 각 DATA 프레임의 길이가 명시적이기 때문에 고전적인 요청 스머글링에 면역이 있다고 여겨집니다. 그러나 프론트엔드 프록시가 요청을 HTTP/1.x로 “다운그레이드”하여 백엔드로 전달하면 그 보호는 사라집니다. 두 개의 서로 다른 파서(HTTP/2 프론트엔드와 HTTP/1 백엔드)가 하나의 요청이 끝나는 지점과 다음 요청이 시작되는 지점에 대해 합의하려고 할 때, 모든 오래된 비동기 트릭이 다시 나타나며 몇 가지 새로운 트릭도 추가됩니다.


다운그레이드가 발생하는 이유

  1. 브라우저는 이미 HTTP/2를 사용하지만, 많은 레거시 오리진 인프라는 여전히 HTTP/1.1만 이해합니다.
  2. 따라서 리버스 프록시(CDN, WAF, 로드 밸런서)는 엣지에서 TLS + HTTP/2를 종료하고 모든 요청을 HTTP/1.1로 재작성합니다.
  3. 변환 단계에서는 오리진이 본문 길이를 결정할 수 있도록 둘 다 Content-Length 및/또는 Transfer-Encoding: chunked 헤더를 생성해야 합니다.

프론트엔드가 HTTP/2 프레임 길이를 신뢰하지만 백엔드가 CL 또는 TE를 신뢰할 때, 공격자는 그들이 동의하지 않도록 강요할 수 있습니다.


두 가지 주요 원시 클래스

변형프론트엔드 길이백엔드 길이일반적인 페이로드
H2.TEHTTP/2 프레임Transfer-Encoding: chunked최종 0\r\n\r\n전송되지 않는 추가 청크 메시지 본문을 포함하여 백엔드가 공격자가 제공한 “다음” 요청을 기다리게 합니다.
H2.CLHTTP/2 프레임Content-Length실제 본문보다 작은 CL을 전송하여 백엔드가 경계를 넘어 다음 요청을 읽도록 합니다.

이들은 고전적인 TE.CL / CL.TE와 본질적으로 동일하며, 단지 HTTP/2가 파서 중 하나를 대체합니다.


다운그레이드 체인 식별

  1. TLS 핸드셰이크에서 ALPN 사용 (openssl s_client -alpn h2 -connect host:443) 또는 curl:
bash
curl -v --http2 https://target

* Using HTTP2가 나타나면 엣지가 H2를 사용하고 있습니다. 2. HTTP/2를 통해 의도적으로 잘못된 CL/TE 요청을 전송합니다(Burp Repeater는 이제 HTTP/2를 강제하는 드롭다운을 제공합니다). 응답이 400 Bad chunk와 같은 HTTP/1.1 오류인 경우, 엣지가 HTTP/1 파서를 위해 트래픽을 변환했다는 증거가 됩니다.


익스플로잇 워크플로우 (H2.TE 예시)

http
:method: POST
:path: /login
:scheme: https
:authority: example.com
content-length: 13      # ignored by the edge
transfer-encoding: chunked

5;ext=1\r\nHELLO\r\n
0\r\n\r\nGET /admin HTTP/1.1\r\nHost: internal\r\nX: X
  1. 프론트엔드는 정확히 13바이트(HELLO\r\n0\r\n\r\nGE)를 읽고 요청이 끝났다고 생각하며 그만큼을 오리진으로 전달합니다.
  2. 백엔드는 TE 헤더를 신뢰하고, 두 번째 0\r\n\r\n을 볼 때까지 계속 읽어 공격자의 두 번째 요청(GET /admin …)의 접두사를 소비합니다.
  3. 나머지(GET /admin …)는 피해자의 뒤에 대기 중인 새로운 요청으로 처리됩니다.

밀반입된 요청을 다음으로 교체합니다:

  • POST /api/logout으로 세션 고정을 강제합니다.
  • GET /users/1234로 피해자 특정 리소스를 탈취합니다.

h2c 밀반입 (명확한 텍스트 업그레이드)

2023년 연구에 따르면, 프론트엔드가 HTTP/1.1 Upgrade: h2c 헤더를 명확한 텍스트 HTTP/2를 지원하는 백엔드로 전달하면, 공격자는 HTTP/1.1만 검증된 엣지를 통해 원시 HTTP/2 프레임을 터널링할 수 있습니다. 이는 헤더 정규화, WAF 규칙 및 심지어 TLS 종료를 우회합니다.

주요 요구 사항:

  • 엣지는 둘 다 Connection: UpgradeUpgrade: h2c를 변경하지 않고 전달합니다.
  • 오리진은 HTTP/2로 증가하고 요청 대기열을 가능하게 하는 연결 재사용 의미를 유지합니다.

완화는 간단합니다 – WebSockets를 제외하고 엣지에서 Upgrade 헤더를 제거하거나 하드코딩합니다.


주목할 만한 실제 CVE (2022-2025)

  • CVE-2023-25690 – Apache HTTP Server mod_proxy 재작성 규칙이 요청 분할 및 밀반입을 위해 연결될 수 있습니다. (2.4.56에서 수정됨)
  • CVE-2023-25950 – HTX 파서가 파이프라인 요청을 잘못 처리할 때 HAProxy 2.7/2.6 요청/응답 밀반입.
  • CVE-2022-41721 – Go MaxBytesHandler가 남은 본문 바이트를 HTTP/2 프레임으로 파싱하여 프로토콜 간 밀반입을 가능하게 했습니다.

도구

  • Burp Request Smuggler – v1.26부터 H2.TE/H2.CL 및 숨겨진 ALPN 지원을 자동으로 테스트합니다. 확장 옵션에서 “HTTP/2 프로빙”을 활성화합니다.
  • h2cSmuggler – Bishop Fox의 Python PoC로 명확한 텍스트 업그레이드 공격을 자동화합니다:
bash
python3 h2csmuggler.py -u https://target -x 'GET /admin HTTP/1.1\r\nHost: target\r\n\r\n'
  • curl/hyper – 수동 페이로드 작성: curl --http2-prior-knowledge -X POST --data-binary @payload.raw https://target.

방어 조치

  1. 종단 간 HTTP/2 – 다운그레이드 변환을 완전히 제거합니다.
  2. 길이 진실의 단일 출처 – 다운그레이드할 때는 항상 유효한 Content-Length를 생성하고 사용자 제공 Content-Length/Transfer-Encoding 헤더를 제거합니다.
  3. 라우트 전에 정규화 – 라우팅/재작성 로직 이전에 헤더 정화 적용합니다.
  4. 연결 격리 – 사용자 간에 백엔드 TCP 연결을 재사용하지 마십시오; “연결당 하나의 요청”은 대기열 기반 공격을 무력화합니다.
  5. WebSocket이 아닌 경우 Upgrade 제거 – h2c 터널링을 방지합니다.

참고 문헌

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기