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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
http2smugl — HTTP/2에서 HTTP/1.1로 변환 시 발생하는 HTTP 요청 스머글링 취약점을 탐지 및 익스플로잇하며, 자동화된 헤더 스머글링 기법을 사용하여 백엔드 파싱 불일치를 식별합니다. | Kitploit
도구/GitHubGitHub/neex/http2smugl
Vulnerability AnalysisWeb Application ExploitationWeb SecurityPenetration Testing
GitHubneex/http2smugl

http2smugl

HTTP/2에서 HTTP/1.1로 변환 시 발생하는 HTTP 요청 스머글링 취약점을 탐지 및 익스플로잇하며, 자동화된 헤더 스머글링 기법을 사용하여 백엔드 파싱 불일치를 식별합니다.

저장소 보기
562741년 전Kitploit 검토 완료

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

http2smugl

이 도구는 프론트엔드 서버가 HTTP/2를 HTTP/1.1으로 변환할 때 발생할 수 있는 HTTP 요청 스머글링(HTTP Request Smuggling)을 탐지하고 악용하는 데 도움을 줍니다.

방식은 다음과 같습니다:

  1. 공격자는 대상 서버(이하 프론트엔드)에 조작된 HTTP/2 요청을 전송합니다.
  2. 해당 요청은 (아마도) HTTP/1.1으로 변환되어 다른 백엔드 서버로 전송됩니다.

공격자는 백엔드 서버가 두 개의 개별 요청으로 해석할 수 있는 요청을 찾고자 합니다.

프론트엔드와 백엔드 간 HTTP/1.1 연결이 keep-alive를 사용하는 경우, 프론트엔드는 같은 연결에 다른 사용자의 요청을 전송할 수도 있습니다. 정상 요청 뒤에 부분적인 요청을 추가하여 연결을 "오염"시킬 수 있다면, 다른 사용자의 요청을 가로챌 수 있습니다.

다른 가능한 시나리오로는 프론트엔드 서버의 보호 및 재작성 우회, 캐시 오염 또는 캐시 디셉션이 있습니다.

HTTP 요청 스머글링에 대한 자세한 내용은 Portswigger Web Security Academy를 참조하십시오.

왜 HTTP/2에 집중하나요?

HTTP/2에서는 모든 HTTP 헤더의 이름과 값이 이진 데이터입니다. 즉, 기술적으로 추가 공백이나 개행 문자를 포함할 수 있습니다.

RFC7540#10.3은 HTTP/2 요청을 HTTP/1으로 변환하는 구현체는 이러한 변환에서 발생하는 문자 집합 제한을 처리해야 한다고 명시하며, 대부분의 구현체는 실제로 이를 거부합니다. 그럼에도 불구하고, 이러한 헤더를 허용하는 구현체를 찾기를 기대합니다. 그러면 변환된 HTTP/1.1 요청이 백엔드로 전달될 때 손상될 수 있습니다.

또 다른 점은 HTTP 요청 스머글링과 관련된 최근 수정 사항이 HTTP/1.1 파서에만 적용되었을 수 있다는 것입니다.

일반적으로, HTTP/1.1의 HTTP 요청 스머글링에 대한 최신 연구를 잘 인지하지 못하고 해당 완화 조치를 포함하지 않은 HTTP/2 구현체가 있을 것이라고 기대합니다.

단일 취약점을 발견하셨나요?

놀랍게도, 그렇습니다!

Cloudflare를 통해 공백 문자를 포함한 헤더를 밀반입할 수 있는 가능성을 발견했습니다. 이를 통해 Cloudflare와 클라이언트 간 스머글링의 문이 열렸습니다(Cloudflare 클라이언트의 소프트웨어가 헤더 이름을 수용하고 트리밍하는 경우). 자세한 내용은 블로그 게시물을 참조하십시오.

아직 공개되지 않은 또 다른 버그 바운티 보고서도 있습니다. 이는 사용자 정의 소프트웨어가 HTTP2 헤더의 개행 문자를 필터링하지 않아서 스머글링이 100% 발생하는 경우를 활용합니다(다른 사용자의 요청을 볼 수 있습니다).

하지만 이러한 유형의 취약점은 실망스러울 정도로 드물다는 점을 이해합니다. HTTP/1.1과 달리 HTTP/2 구현체는 많지 않으며, 대부분 보안을 염두에 두고 만들어져 의심스럽거나 유효하지 않은 헤더를 거부합니다.

탐지 알고리즘

이 도구에는 대상이 HTTP 요청 스머글링 공격에 취약한지 자동으로 탐지하는 하위 명령어가 있습니다. 이 기능의 알고리즘은 이 섹션에서 설명합니다.

HTTP 요청 스머글링 공격을 수행하려면 먼저 헤더 하나( Content-Length 또는 Transfer-Encoding )를 "밀반입"해야 합니다. 즉, 요청 본문의 끝을 제어하며 프론트엔드에서는 처리되지 않고 백엔드에서는 처리되는 헤더를 전송해야 합니다.

이는 일반적으로 헤더를 어떤 방식으로 수정하여 달성됩니다: 이름 끝에 공백이나 탭을 추가하거나, 값을 반등가 값으로 대체하는 등.

취약점 탐지 알고리즘의 기본 아이디어는 서버가 밀반입된 헤더를 마치 Content-Length 또는 Transfer-Encoding 인 것처럼 실제로 처리하는지 감지하는 것입니다. 이를 위해 유효한 값과 유효하지 않은 값의 헤더를 사용하여 여러 요청을 전송한 후, 두 그룹의 응답을 구별할 수 있는 방법이 있는지 확인합니다.

따라서 도구 출력에는 "취약/비취약"이라는 단어가 포함되지 않습니다. 단지 이 두 그룹의 요청에 대한 응답을 구별할 수 있는지 여부만 알려줍니다.

도구는 다음 두 조건 중 적어도 하나가 충족되면 두 HTTP 응답 세트를 구별 가능한 것으로 간주합니다:

  1. 응답 코드 세트가 교차하지 않음
  2. 응답 길이 세트가 서로 분리 가능함(예: 모든 "유효한" 응답이 1000바이트를 초과하고 모든 "유효하지 않은" 응답이 그 이하인 경우)

시간 초과는 다른 어떤 것과도 같지 않은 고유한 상태 코드 값으로 처리됩니다. 따라서 도구는 기존의 "시간 측정 기반 탐지" 방식을 대체합니다.

예를 들어 보겠습니다. transfer-encoding 헤더를 대시를 밑줄로 대체하여 밀반입하려고 한다고 가정합니다.

transfer_encoding:zalupa 를 보낼 때마다 서버가 400 상태로 응답하고, transfer_encoding:chunked 일 때는 응답이 중단된다면, 서버가 헤더를 transfer encoding 값으로 처리할 가능성이 높습니다. 이론적으로 프론트엔드나 백엔드 서버 모두 가능합니다.

첫 번째 경우는 밀반입되지 않은 버전의 헤더도 보낼 수 있으므로 흥미롭지 않습니다. 두 번째 경우가 우리가 찾는 것입니다. 모든 통신이 HTTP/2를 통해 이루어지므로 첫 번째 경우는 대부분 피할 수 있습니다. HTTP/2 서버는 요청 헤더와 무관한 다른 방식으로 요청 본문의 끝을 결정하며, HTTP/1.1의 청크 형식(16진수 청크 길이를 사용하는 형식)으로 본문이 전달될 것이라고 기대하지 않습니다.

구체적인 탐지 기법의 변형은 다음과 같습니다:

  1. 밀반입된 버전의 Transfer-Encoding: chunked (예: transfer_encoding:chunked)와 본문의 유효/유효하지 않은 값을 함께 전송합니다. 유효한 본문은 0\r\n\r\n, 유효하지 않은 본문은 999\r\n 입니다.

    응답이 다른 경우, 백엔드 서버가 밀반입된 헤더를 수신하여 처리한다고 확신할 수 있습니다. 프론트엔드가 이렇게 할 이유는 없습니다. HTTP/2는 우리가 보낸 청크 형식을 사용하지 않으므로 유효하지 않기 때문입니다.

    유효하지 않은 요청의 경우 백엔드가 더 많은 데이터가 도착하기를 기다리면서 중단(즉, 요청 시간 초과)될 것으로 예상합니다.

    이는 가장 신뢰할 수 있는 탐지 변형입니다. 본문을 읽을 때 서버가 중단되면, HTTP/2 요청에서 HTTP/1.1 전송 인코딩이 사용되지 않으므로 무언가 잘못되었을 가능성이 큽니다.

  2. 밀반입된 버전의 Transfer-Encoding 과 다시 다른 본문을 전송합니다. 유효한 본문으로 0\r\n\r\n, 유효하지 않은 본문으로 X\r\n\r\n 입니다.

    위와 동일한 경우이지만, 본문을 읽지 않고 백엔드가 최소한 유효성을 검사할 것으로 예상합니다.

  3. 밀반입된 버전의 Content-Length 헤더를 값 1 과 -1 로 전송합니다.

    두 값 모두 프론트엔드의 관점에서는 유효하지 않습니다. HTTP/2에는 본문 길이를 결정하는 다른 메커니즘이 있으며, 두 경우 모두 실제 요청 본문이 전송되지 않습니다. 응답이 다른 경우, 헤더를 파싱한 것은 백엔드 서버라고 가정합니다.

    이 방법은 가장 신뢰도가 낮습니다. 프론트엔드가 Content-Length에 유효하지 않은 값이 있을 때와 실제 길이와 일치하지 않을 때 다른 오류를 발생시킬 수 있기 때문입니다.

여러 쌍의 유효/유효하지 않은 요청을 전송함으로써 무작위 오탐 가능성을 줄일 수 있습니다. 반면, "유효한" 요청에 대한 응답과 "유효하지 않은" 요청에 대한 응답을 분리할 방법이 없다고 판단되면 조기에 중단할 수 있습니다.

밀반입 기법

도구는 헤더를 다양한 방식으로 수정하여 여러 밀반입 기법을 시도합니다. 이들 중 어느 것도 새롭거나 명확하지 않습니다.

공백

헤더를 밀반입하기 위해 공백을 추가합니다. 이것은 가장 일반적이고 고전적인 방법입니다. 헤더가 프론트엔드에서 처리되지 않고 그대로 백엔드로 전송되어 공백이 제거되기를 기대합니다.

도구는 다양한 문자를 공백으로 시도합니다: , \t, \v, \x00 및 유니코드 공백 문자들을 포함합니다.

밑줄

헤더를 밀반입하기 위해 대시(-)를 밑줄(_)로 대체합니다. 만약 백엔드가 어떤 면에서 CGI의 영향을 받았다면, Header-Name 과 같은 헤더를 HEADER_NAME 형식으로 변환할 수 있습니다. 따라서 대시는 어쨌든 밑줄이 됩니다. 본문을 파싱하는 방법을 결정할 때, 이러한 백엔드는 헤더 사전에서 CONTENT_LENGTH / TRANSFER_ENCODING 의 값을 요청할 것이며, 그 값이 존재할 것입니다.

개행 문자

이것은 HTTP/2 전용입니다. HTTP/2는 이진 프로토콜이므로 헤더 이름이나 값에 개행 문자를 전송할 수 있습니다. 표준은 이를 금지하지만, 이를 여전히 허용하는 구현체를 찾기를 기대합니다.

HTTP/2에서 HTTP/1.1으로 변환하는 과정에서 헤더가 두 개의 다른 헤더로 분할되므로, 백엔드에는 요청이 다르게 보일 것입니다.

헤더를 밀반입하기 위해 개행 문자 뒤에 헤더 이름과 값을 넣습니다. 예를 들어, 이름이 "Transfer-Encoding"이고 값이 "chunked"인 헤더는 이름이 "fake"이고 값이 "fake\r\ntransfer-encoding: chunked"인 헤더가 됩니다.

UTF 문자

백엔드가 고수준 언어를 사용하고 헤더 검증을 충분히 수행하지 않는다고 가정해 봅시다. 그렇다면 다른 작업을 수행하기 전에 이름을 대문자로 변환할 수 있으며, 이를 유니코드 인식 함수를 사용하여 수행할 수 있습니다. 다행히도 TRANSFER-ENCODING 에는 S 문자가 포함되어 있으며, 이는 ſ (\u017f)의 대문자입니다.

마찬가지로, Transfer-Encoding 의 값을 소문자로 변환하는 백엔드를 찾을 수 있습니다. chunKed 대신 \u212a 를 K 대신 사용하여 chunked 를 전송합니다.

물론 프론트엔드가 UTF-8 헤더 이름/값을 백엔드로 전달해야 합니다.

사용법

도구를 설치하려면 go install github.com/neex/http2smugl@latest 를 실행하십시오.

이 도구에는 request 와 detect 라는 두 개의 하위 명령어가 있습니다. 첫 번째는 단순히 HTTP/2 요청을 조작하기 위한 것입니다. 대부분의 클라이언트 도구는 유효하지 않은 헤더를 허용하지 않으므로, 사용자 입력을 있는 그대로 서버에 전송하는 도구가 있으면 편리합니다.

다른 하나는 detect 입니다. HTTP 요청 스머글링의 다양한 기법을 시도하여 대상이 취약한지 탐지합니다. 탐지 알고리즘은 복잡합니다. 이 내용을 읽고 의견을 보내주시면 감사하겠습니다. 해당 섹션에서 아래에 설명되어 있습니다.

http2smugl request

이 하위 명령어를 사용하여 (약간 형식이 잘못된) http2 요청을 전송합니다. 첫 번째 매개변수는 URL이고, 나머지는 이름:값 형식의 헤더입니다(콜론 뒤에 공백이 없음). 백슬래시 이스케이프가 지원됩니다. \r, \n 및 \xXX 이스케이프 코드를 사용할 수 있습니다. 예를 들어, 콜론을 포함하는 헤더 이름을 전송하려면 \x3a 를 사용하십시오(예: name\x3awith\x3acolons:value).

http2smugl detect

이 하위 명령어는 다양한 기법을 사용하여 HTTP 요청 스머글링을 탐지합니다. 사용하려면 http2smugl detect [HTTPS URL] 을 실행하십시오.

명령어는 서버가 밀반입된 헤더를 파싱한다는 것을 감지할 수 있는 경우에만 출력합니다. 이것이 의미하는 바를 이해하려면 해당 섹션을 읽어주십시오.

HTTP/3 지원

HTTP/3(quic)에 대한 실험적 지원이 구현되었습니다. 그러나 HTTP/3 관련 버그를 찾지 못했으므로 사용을 권장하지 않습니다.

request 하위 명령어에서 HTTP/3을 사용하려면 URL에서 https 대신 https+h3:// 프로토콜을 제공하십시오. detect 명령어에서도 동일하게 지원됩니다.

request 하위 명령어에는 --try-http3 플래그도 있습니다. 이 플래그는 URL에 프로토콜이 지정되지 않은 경우(호스트 이름만 있는 경우) 동작을 변경합니다. 플래그가 있으면 명령어는 명령줄 또는 대상 파일의 항목에 대해 https+h3 프로토콜을 시도합니다(HTTP/2도 함께). 예를 들어, http2smugl detect --try-http3 www.example.com 은 HTTP/3과 HTTP/2를 모두 시도하지만, http2smugl detect --try-http3 https://www.example.com/ 은 여전히 HTTP/2만 시도합니다.

알려진 오탐

이 섹션에서는 도구가 응답을 "구별 가능"하다고 말하지만 취약점이 존재할 수 없는 몇 가지 사례를 설명합니다.

ELB

Amazon의 Elastic Load Balancer는 HTTP 요청 스머글링에 대한 여러 완화 조치를 구현합니다. 기본적으로 모든 요청을 거부하지는 않지만, ELB는 "의심스러운" 헤더가 포함된 요청을 전송한 후에는 연결을 재사용하지 않습니다. 따라서 실제 공격은 불가능합니다.

ELB를 다루고 있는지 감지하려면 Server 응답 헤더를 사용할 수 있습니다. 필터링된 경우, content__length 헤더(밑줄 두 개 주의)와 값 -1을 전송해 보십시오. 400이 반환되면 ELB 또는 다른 WAF일 가능성이 높습니다(아래 참조).

Apache Traffic Server

Apache Traffic Server는 주로 Yahoo에서 사용됩니다. HTTP/2를 특이한 방식으로 처리합니다. 메모리에서 HTTP/1.1으로 변환한 다음 결과 요청을 다시 파싱합니다. 따라서 헤더가 기술적으로 "밀반입"될 수 있지만, 취약점으로 이어질 방법은 없습니다. 동일한 바이트를 HTTP/1.1 연결에 전송할 수 있기 때문입니다.

ATS를 다루고 있는지 감지하는 가장 쉬운 방법(Server 헤더 외에)은 TRACE 요청을 전송하는 것입니다. 요청에 Max-Forwards: 0 헤더가 있으면 ATS는 기본적으로 TRACE 요청에 대한 응답을 백엔드로 전달하지 않고 반환합니다.

Microsoft IIS

Microsoft IIS는 HTTP/2 본문 내 청크 인코딩 디코딩을 지원하는 것으로 보입니다. 이는 이상한 동작이지만 보안 관점에서는 무해합니다.

IIS를 다루고 있는지 감지하려면 "transfer-encoding:chunked" 헤더와 올바르지 않은 청크 본문이 포함된 요청을 전송해 보십시오. Server 헤더에 Microsoft-HTTPAPI 또는 이와 유사한 내용이 보이면 그것입니다.

기타 WAF

WAF는 의심스러운 헤더를 감지하는 것이 업무입니다. 이로 인해 도구가 "구별 가능"이라고 말하는 경우가 있습니다. WAF는 content_length:-1 과 같은 것을 차단하고 content_length:1 은 허용할 수 있습니다. 필터가 우연히 이러한 결정을 내리기 때문입니다.

Server 헤더에 WAF가 표시되면 오탐일 가능성이 높습니다.

연락처

이 주제에 대한 의견이 있으시면 Twitter의 @emil_lerner 또는 Telegram의 @neexemil로 연락하시거나 GitHub에 이슈를 게시해 주십시오.

도구 다운로드